From 5c6afe831d9fe70906aefb124b3554e423482d80 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 25 Oct 2026 04:34:40 +0000 Subject: [PATCH 1/2] chore(deps): bump the dev-tooling group across 1 directory with 13 updates Bumps the dev-tooling group with 13 updates in the / directory: | Package | From | To | | --- | --- | --- | | [@astrojs/markdown-remark](https://github.com/withastro/astro/tree/HEAD/packages/markdown/remark) | `7.3.2` | `7.3.4` | | [@axe-core/playwright](https://github.com/dequelabs/axe-core-npm) | `4.13.0` | `4.14.0` | | [@playwright/test](https://github.com/microsoft/playwright) | `1.64.0` | `1.64.1` | | [@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue/tree/HEAD/packages/plugin-vue) | `6.0.9` | `6.0.10` | | [astro](https://github.com/withastro/astro/tree/HEAD/packages/astro) | `7.3.7` | `7.4.2` | | [es-module-lexer](https://github.com/guybedford/es-module-lexer) | `3.0.3` | `3.0.4` | | [postcss](https://github.com/postcss/postcss) | `8.5.29` | `8.5.31` | | [react](https://github.com/react/react/tree/HEAD/packages/react) | `19.3.0` | `19.3.1` | | [react-dom](https://github.com/react/react/tree/HEAD/packages/react-dom) | `19.3.0` | `19.3.1` | | [smol-toml](https://github.com/squirrelchat/smol-toml) | `1.9.0` | `1.9.1` | | [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `8.3.3` | `8.3.5` | | [vue](https://github.com/vuejs/core) | `3.5.43` | `3.5.44` | | [zod](https://github.com/colinhacks/zod) | `4.6.5` | `4.6.7` | Updates `@astrojs/markdown-remark` from 7.3.2 to 7.3.4 - [Release notes](https://github.com/withastro/astro/releases) - [Changelog](https://github.com/withastro/astro/blob/main/packages/markdown/remark/CHANGELOG.md) - [Commits](https://github.com/withastro/astro/commits/@astrojs/markdown-remark@7.3.4/packages/markdown/remark) Updates `@axe-core/playwright` from 4.13.0 to 4.14.0 - [Release notes](https://github.com/dequelabs/axe-core-npm/releases) - [Changelog](https://github.com/dequelabs/axe-core-npm/blob/develop/CHANGELOG.md) - [Commits](https://github.com/dequelabs/axe-core-npm/compare/v4.13.0...v4.14.0) Updates `@playwright/test` from 1.64.0 to 1.64.1 - [Release notes](https://github.com/microsoft/playwright/releases) - [Commits](https://github.com/microsoft/playwright/compare/v1.64.0...v1.64.1) Updates `@vitejs/plugin-vue` from 6.0.9 to 6.0.10 - [Release notes](https://github.com/vitejs/vite-plugin-vue/releases) - [Changelog](https://github.com/vitejs/vite-plugin-vue/blob/main/packages/plugin-vue/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite-plugin-vue/commits/plugin-vue@6.0.10/packages/plugin-vue) Updates `astro` from 7.3.7 to 7.4.2 - [Release notes](https://github.com/withastro/astro/releases) - [Changelog](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md) - [Commits](https://github.com/withastro/astro/commits/astro@7.4.2/packages/astro) Updates `es-module-lexer` from 3.0.3 to 3.0.4 - [Release notes](https://github.com/guybedford/es-module-lexer/releases) - [Commits](https://github.com/guybedford/es-module-lexer/compare/3.0.3...3.0.4) Updates `postcss` from 8.5.29 to 8.5.31 - [Release notes](https://github.com/postcss/postcss/releases) - [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/postcss/postcss/compare/8.5.29...8.5.31) Updates `react` from 19.3.0 to 19.3.1 - [Release notes](https://github.com/react/react/releases) - [Changelog](https://github.com/react/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/react/react/commits/v19.3.1/packages/react) Updates `react-dom` from 19.3.0 to 19.3.1 - [Release notes](https://github.com/react/react/releases) - [Changelog](https://github.com/react/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/react/react/commits/v19.3.1/packages/react-dom) Updates `smol-toml` from 1.9.0 to 1.9.1 - [Release notes](https://github.com/squirrelchat/smol-toml/releases) - [Commits](https://github.com/squirrelchat/smol-toml/compare/v1.9.0...v1.9.1) Updates `vite` from 8.3.3 to 8.3.5 - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v8.3.5/packages/vite) Updates `vue` from 3.5.43 to 3.5.44 - [Release notes](https://github.com/vuejs/core/releases) - [Changelog](https://github.com/vuejs/core/blob/main/CHANGELOG.md) - [Commits](https://github.com/vuejs/core/compare/v3.5.43...v3.5.44) Updates `zod` from 4.6.5 to 4.6.7 - [Release notes](https://github.com/colinhacks/zod/releases) - [Commits](https://github.com/colinhacks/zod/compare/v4.6.5...v4.6.7) --- updated-dependencies: - dependency-name: "@astrojs/markdown-remark" dependency-version: 7.3.4 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-tooling - dependency-name: "@axe-core/playwright" dependency-version: 4.14.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-tooling - dependency-name: "@playwright/test" dependency-version: 1.64.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-tooling - dependency-name: "@vitejs/plugin-vue" dependency-version: 6.0.10 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-tooling - dependency-name: astro dependency-version: 7.4.2 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-tooling - dependency-name: es-module-lexer dependency-version: 3.0.4 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-tooling - dependency-name: postcss dependency-version: 8.5.31 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-tooling - dependency-name: react dependency-version: 19.3.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-tooling - dependency-name: react-dom dependency-version: 19.3.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-tooling - dependency-name: smol-toml dependency-version: 1.9.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-tooling - dependency-name: vite dependency-version: 8.3.5 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-tooling - dependency-name: vue dependency-version: 3.5.44 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dev-tooling - dependency-name: zod dependency-version: 4.6.7 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-tooling ... Signed-off-by: dependabot[bot] --- apps/demo/package.json | 2 +- package-lock.json | 1120 ++++++++++++---------------------------- package.json | 26 +- 3 files changed, 355 insertions(+), 793 deletions(-) diff --git a/apps/demo/package.json b/apps/demo/package.json index 5c2973ba1..e79e538da 100644 --- a/apps/demo/package.json +++ b/apps/demo/package.json @@ -9,7 +9,7 @@ }, "dependencies": { "@j3w1/ui": "*", - "vue": "3.5.43", + "vue": "3.5.44", "vue-router": "5.4.0" } } diff --git a/package-lock.json b/package-lock.json index 63eb88d20..7b5e0d7f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,26 +15,26 @@ "@j3w1/ui": "*" }, "devDependencies": { - "@astrojs/markdown-remark": "7.3.2", - "@axe-core/playwright": "4.13.0", - "@playwright/test": "1.64.0", - "@vitejs/plugin-vue": "6.0.9", - "astro": "7.3.7", - "es-module-lexer": "3.0.3", + "@astrojs/markdown-remark": "7.3.4", + "@axe-core/playwright": "4.14.0", + "@playwright/test": "1.64.1", + "@vitejs/plugin-vue": "6.0.10", + "astro": "7.4.2", + "es-module-lexer": "3.0.4", "fflate": "0.8.3", "jsonc-parser": "3.3.1", "parse5": "8.0.1", - "postcss": "8.5.29", + "postcss": "8.5.31", "postcss-value-parser": "4.2.0", - "react": "19.3.0", - "react-dom": "19.3.0", - "smol-toml": "1.9.0", + "react": "19.3.1", + "react-dom": "19.3.1", + "smol-toml": "1.9.1", "teleproto": "1.229.1", "typescript": "7.0.2", - "vite": "8.3.3", - "vue": "3.5.43", + "vite": "8.3.5", + "vue": "3.5.44", "yaml": "2.9.1", - "zod": "4.6.5" + "zod": "4.6.7" }, "engines": { "node": "24.x", @@ -46,7 +46,7 @@ "version": "4.0.0", "dependencies": { "@j3w1/ui": "*", - "vue": "3.5.43", + "vue": "3.5.44", "vue-router": "5.4.0" } }, @@ -270,33 +270,33 @@ } }, "node_modules/@astrojs/internal-helpers": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.12.0.tgz", - "integrity": "sha512-pKPuwCDtO0L7zgmt1JGd9X4Aes1+0SX3IEBSqBNPHsScYdPMlfmed3Y7DTbXyF7E+8ylnb563o/0OzGQPOFehw==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.13.0.tgz", + "integrity": "sha512-20jxQqnSmpskcGyad7N5l6Xf1gz0UCa6lNde44bEBdaXGpncEYfAZJ142r2ZgzBaG4dUyzGmhqZWv1INU2eiHQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/hast": "^3.0.4", + "@types/hast": "^3.0.5", "@types/mdast": "^4.0.4", - "picomatch": "^4.0.4", + "picomatch": "^4.0.7", "retext-smartypants": "^6.2.0", - "shiki": "^4.0.2", - "smol-toml": "^1.8.0", + "shiki": "^4.5.0", + "smol-toml": "1.9.1", "unified": "^11.0.5", "yaml": "^2.9.1" } }, "node_modules/@astrojs/markdown-remark": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-7.3.2.tgz", - "integrity": "sha512-ubszw8SVEI4OHR5Y+0jTbkmzG8xatrW47iAkQNqH7wUM1bky7DOnr51FGgoUdXt/fmKpUl7sRRX9talmU64Y+g==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-7.3.4.tgz", + "integrity": "sha512-AB8S4EQKSryzH624iMDtvC+1AD5nSPzYpCXxc7e1H5ydXhv9B5Td2QfCPA0JyEwqsJpsIsPlW0iOqiy1imdqYw==", "dev": true, "license": "MIT", "dependencies": { - "@astrojs/internal-helpers": "0.12.0", - "@astrojs/prism": "4.0.2", + "@astrojs/internal-helpers": "0.13.0", + "@astrojs/prism": "4.1.1", "@mdx-js/mdx": "^3.1.1", - "acorn": "^8.16.0", + "acorn": "^8.19.0", "estree-util-visit": "^2.0.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", @@ -308,8 +308,8 @@ "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", - "remark-smartypants": "^3.0.2", - "source-map": "^0.7.6", + "remark-smartypants": "^3.0.3", + "source-map": "^0.8.0", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.1.0", @@ -317,56 +317,69 @@ "vfile": "^6.0.3" } }, + "node_modules/@astrojs/markdown-remark/node_modules/source-map": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0.tgz", + "integrity": "sha512-d8EqvL+k/SOXCreS/SUzg2ciyHqBBLcN/yuRjFsbvVhHTE2pgei7oAhmPM7kWFbkX6OSMQfUq4KbkF3au9lhYQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, "node_modules/@astrojs/markdown-satteri": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@astrojs/markdown-satteri/-/markdown-satteri-0.4.3.tgz", - "integrity": "sha512-PFbEHPnwUlLvpXd7RXrrKM+j12akF4bG+DSuNuoN+3eiwjOwp4HaPi+QQdbkBV7QEYXmzyKca50OJsmGxhNIUA==", + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-satteri/-/markdown-satteri-0.4.5.tgz", + "integrity": "sha512-0IeGdoFbv0f+442KJhYS44Wg8F3MuHmRsxIEYuFyqkjRubc6dPBFZ7azor5t4AeXLQoT5A5h9HyViKpd70Dl9w==", "dev": true, "license": "MIT", "dependencies": { - "@astrojs/internal-helpers": "0.12.0", - "@astrojs/prism": "4.0.2", + "@astrojs/internal-helpers": "0.13.0", + "@astrojs/prism": "4.1.1", "github-slugger": "^2.0.0", - "satteri": "^0.10.3" + "satteri": "^0.10.5" } }, "node_modules/@astrojs/prism": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-4.0.2.tgz", - "integrity": "sha512-KTivpmnz6lDsC6o9H4+DNm2SrE/GHzw8cNAvEJwAvUT+eoaEnn/4NtbDNfRRaxaJHdp15gf+tfHAWiXR4wB3BA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-4.1.1.tgz", + "integrity": "sha512-sXlAXJX6t4QfuLg+CuCDzpg7NoxWcyb4paFprgtFppLeisCBmh935h+tJ5CWXfsXEoW2IDy/ihbRMtiu28Chjw==", "dev": true, "license": "MIT", "dependencies": { "prismjs": "^1.30.0" }, "engines": { - "node": ">=22.12.0" + "node": ">=22.23.4" } }, "node_modules/@astrojs/telemetry": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.3.tgz", - "integrity": "sha512-C1TLn5sPJr0x4vk56piHWKbnqlEB8BKyte5Y45V02U+D7BGO5eMqZDH5aPjnkXQWJggvmsTXxH03QMZ9NgWLzQ==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.4.1.tgz", + "integrity": "sha512-SMkvMsGOpM0FMAoT5pzhgI3LZC0JSPWf7Evwop+fZ3N6UkusPM7lI+sOJjMNI5OJrVoiei1/AGo1cY7sikTc5A==", "dev": true, "license": "MIT", "dependencies": { "ci-info": "^4.4.0", "dset": "^3.1.4", "is-docker": "^4.0.0", - "package-manager-detector": "^1.6.0" + "package-manager-detector": "^1.9.0" }, "engines": { - "node": "18.20.8 || ^20.3.0 || >=22.0.0" + "node": ">=22.23.4" } }, "node_modules/@axe-core/playwright": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.13.0.tgz", - "integrity": "sha512-6YLx+kxXu5GJceG4ozFg+33a2EMTdjYwWGloJ3sb9Kta5pp+ZNS53uxGVog5JetIY8s++P5UrtX+cri+u0VAVg==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.14.0.tgz", + "integrity": "sha512-SGUhG5PIHd2eMdpgBF2PyQLOhX+qyDR2PT4cmoS4Qk2ak+jX/rrSvst9l0PGv5WTHolKpUMvVmoHpr4cZgf1RQ==", "dev": true, "license": "MPL-2.0", "dependencies": { - "axe-core": "~4.13.0" + "axe-core": "~4.14.0" + }, + "engines": { + "node": ">=22.12.0" }, "peerDependencies": { "playwright-core": ">= 1.0.0" @@ -391,9 +404,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.29.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", - "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "version": "7.29.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.9.tgz", + "integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==", "license": "MIT", "dependencies": { "@babel/types": "^7.29.8" @@ -672,422 +685,6 @@ "tslib": "^2.4.0" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", - "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", - "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", - "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", - "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", - "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", - "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", - "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", - "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", - "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", - "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", - "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", - "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", - "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", - "cpu": [ - "mips64el" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", - "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", - "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", - "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", - "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", - "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", - "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", - "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", - "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", - "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", - "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", - "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", - "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", - "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@img/colour": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", @@ -1785,9 +1382,9 @@ "license": "MIT" }, "node_modules/@oxc-project/types": { - "version": "0.153.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.153.0.tgz", - "integrity": "sha512-jSNrRIyvPVLL5E1z/tS5zLAprosGz/FuI1PWwEOz59j3E4TTTzSpqKb/RDGqJhhW0QHYISGXxq582wGx6T11Tw==", + "version": "0.155.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.155.0.tgz", + "integrity": "sha512-SeE8JPwW1xs1tHeNycjUtUBdhorRa8o4jlvjwk49R7/Z291i+4DQa7JJIgOm/TaYQZx+QrPQbVJ/9c8dMIZN8Q==", "devOptional": true, "license": "MIT", "funding": { @@ -1795,13 +1392,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.64.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.64.0.tgz", - "integrity": "sha512-oTN9FNYuN6bqQMwiho6jJKLCG2/QOYCixGXuCjRmzOq23eODeukuY2XiAVoVpAECbuezMt1MHQjAiQxK8F+Y+g==", + "version": "1.64.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.64.1.tgz", + "integrity": "sha512-IaYGml/nSOiZWROfPtuIL7neuu9qDOZ3TNvNljUIrhDMxiGTgPjzj/g9p9RxpS2tSepPDRY+UwAaEeiKtUvIAg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.64.0" + "playwright": "1.64.1" }, "bin": { "playwright": "cli.js" @@ -1811,9 +1408,9 @@ } }, "node_modules/@rolldown/binding-android-arm-eabi": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.13.tgz", - "integrity": "sha512-Vu/NICrgdRvUOeaJZIyB2FP63s6fO/4ud5l8dXmxDx9yDyn+mN0y+gsvsVviSli+T361Aqo0h46EuMoobrwawA==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.15.tgz", + "integrity": "sha512-aLcgK9gIJ3YRvrrtfSBbRa27F5WrpiTaPulnFpsHPxpUHgFlSgnU4854MHwoRGEBhfRJDWCS2WQ7lIjskE9Olw==", "cpu": [ "arm" ], @@ -1827,9 +1424,9 @@ } }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.13.tgz", - "integrity": "sha512-6LEoIrGy5vvCd2boNnv2soPSUZj/PRvhp8R/t9KlX+mIZxThIE/ZqxrGXxmuNX0FuvQFvLdZr7S4HrYpYBVhEQ==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.15.tgz", + "integrity": "sha512-xD7DdZCrbThKuxNg7ooQmvp07ys4J/pnSEMTG3/OdOWl6daC67m/Q4fL78sRHMxTH/N4fGUbYhcPM0MF5WFHkg==", "cpu": [ "arm64" ], @@ -1843,9 +1440,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.13.tgz", - "integrity": "sha512-CaJSRzlQ6Q+zkDMVA9OkVxBjVoPRCDEE3v0FSJ9kIQBgRjFApA3Si4ijhbNVUji7ZJt+PfO0e46qy4nPInHUPA==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.15.tgz", + "integrity": "sha512-m2WuQ6r0B4OTYxyPpNLtXaMRbRDUbG8YQV2Q3KTdSSK8Th6KHCnC8jVCJt8bvYeSB5WivkkNbc85mKadaSdOxA==", "cpu": [ "arm64" ], @@ -1859,9 +1456,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.13.tgz", - "integrity": "sha512-e4r340I5hxSzJkD3YJBxgzq/rJ3wwxwdLLb2FPt1Zpyem20nrQPT11DDEEkazwxaHumH8wpglsp/Ozgj/wT6mw==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.15.tgz", + "integrity": "sha512-5RtnsHM36nodM9WbMy+zip0LGS/G+y5wro5RHrpOlr4ac24+1zSi9kiV2MP1myZeZ/ifEHfulQcWjnAXzc2C2A==", "cpu": [ "x64" ], @@ -1875,9 +1472,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.13.tgz", - "integrity": "sha512-hoBWDZ4/K/mJKVMbsgUd1jfpA2DiOrJ54mpegObU9TBHBBrtX4FLIXJJQRDPZ/2Dn91GvPob+Z2hwKJzf4E5SQ==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.15.tgz", + "integrity": "sha512-g3l09pyFqhu+135JKkbkwiKGQmwU5hUMUPJ4VdBADvuqR8d33L6H578rh8m7rtxbdp+VmX/+nzI7nvhSZlzpUQ==", "cpu": [ "x64" ], @@ -1891,9 +1488,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.13.tgz", - "integrity": "sha512-oF9fZu3vTWnTiVAkDFxU9PJLt1nh20K9RRpuHsR7ZnE2L7XookBbDBVLojCVSLGbvtSlxeUNnjAj6DbNsKyzbg==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.15.tgz", + "integrity": "sha512-nIe3VugI97nGQtspPxDqA4sXMUpeiocKIP/CqpY/u/vgbT+alX+cVxu1C/oVBPKg4feNTmYovE91v4DgXvXNwQ==", "cpu": [ "arm" ], @@ -1907,9 +1504,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.13.tgz", - "integrity": "sha512-DTpb/+jMiqWMPgphn4ksW1zW+XLJ6dJJ9FMvnIk9I291LhCctMPhMYJrP5t9p6C9qa3KXadDdUEZHBaPh3kNxQ==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.15.tgz", + "integrity": "sha512-iTBjXx+B5QSvgI89lJfmqh4wTh8NabR1YZIIN3hNx4zSG0EVfVqkOvLulNpG4251pbd6/IAmZ/LefVk1Y4rPhw==", "cpu": [ "arm64" ], @@ -1926,9 +1523,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.13.tgz", - "integrity": "sha512-xU+Kvv9N2A3SY35zFh1FWWNjxbadE/BKeqnkXe7vScU4GZsw757BlVmDLITZEq8DPpk6m7uoDYkK7P+x/uU5Ow==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.15.tgz", + "integrity": "sha512-uN26XOnVR7rqQupG3V9oAG2EGGatWjcJHOeDOHUFCh4TBWmP2tHTFoVN13aYbwfm0aHqJAEmcwhAu6sooIjfqQ==", "cpu": [ "arm64" ], @@ -1945,9 +1542,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.13.tgz", - "integrity": "sha512-XMk/hnhh25oQ756Lclb1Q11h4ll0xC0Esa5w4Vzp+mAE2S3AGJgeM0SonrIgY8fHhjarb6hcoTuwoFG0VVP2ig==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.15.tgz", + "integrity": "sha512-9nWkcdd+H+XhaA3fQIwpHnKIrfx/PQ6rO0pivr78Og07tXlUlctBBJoEYLPfhTmCR/QxEVdn6uPjHV5SymPhdw==", "cpu": [ "ppc64" ], @@ -1964,9 +1561,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.13.tgz", - "integrity": "sha512-U1BoTHYmlywE2n3HUWjzZ+8EQsKr+OwpxYuDWaubx42tUL8QSL7nOqRz/NVHanibbFP3M1Rxuprz/wNcbMKjqw==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.15.tgz", + "integrity": "sha512-Ggh0ciFjLwIusLSLz7LZYEaGdxOAUJXI+Qu5JCbhPJJHEt8vP+IjRATTJheiJsdzzTYgUiHUiw3X1Ea3ZpMBdA==", "cpu": [ "s390x" ], @@ -1983,9 +1580,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.13.tgz", - "integrity": "sha512-J4cm80Pc6wEwV5AZ42o62sIQgDk+Y7R2s646jIwuvO+4V46QB58N4vVuMPWCBaNgursXLpmUWJV//WQAkPvHBQ==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.15.tgz", + "integrity": "sha512-FHg60rS6DBePAYZ9X9F67x+JObFdmgn6tupA1C/a3B+CufFmTD4mX+e8M75tCiAO3foR/6xwVBI0KQiI7sn/rw==", "cpu": [ "x64" ], @@ -2002,9 +1599,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.13.tgz", - "integrity": "sha512-W0euZS40U4V6JkmEnVCIX9mcsL6cbXQ4X8c2w+MMOIjFg68TXUW+u3RT+2e1t1pv9mg/EP3pDtK3POXdQ7Rxyw==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.15.tgz", + "integrity": "sha512-/cvV/7v5VGz/moiz0XKRj2dE8DzsKyhIu1KpOvJGPjRywg3yscON889UGvAe8zfiJLHup7VLjBduoGWi3HusWQ==", "cpu": [ "x64" ], @@ -2021,9 +1618,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.13.tgz", - "integrity": "sha512-do/AF/4n9MRshia3a5aXoy8xM2c6mgfT6D7H/dY6my5z+hfCIR4ab7mk4IRj++nsEQpKy39kd0DQnDq+r692tw==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.15.tgz", + "integrity": "sha512-MyzC5Hrv/sm+Z7TSGKP/j8001RO2xQm1zOpCNVL4j0cY/VhBZviludA2YFQ7i4lH6ZAXxQm0lcMdBzM+99mE7w==", "cpu": [ "arm64" ], @@ -2037,9 +1634,9 @@ } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.13.tgz", - "integrity": "sha512-6FtUf2cJZobutJdxnGYX8z0vtbgqU0b2v8vfBhkXb9wp2MppMFtkunE+IaOntyi01rkIQoPW2GHABtfzsC0BRQ==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.15.tgz", + "integrity": "sha512-+PgYiS+AH5omy6L45ZLxybasauJaj3M8buoT83D+nzPmCayXlxUV9hydhciCKVyIg0B/v0BtXPDE1uGqNwCPpg==", "cpu": [ "arm64" ], @@ -2053,9 +1650,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.13.tgz", - "integrity": "sha512-UKhFaZTeTcbKrb3iU82m17jVcPEAoqDkCN5MBqgPyZSwp/cQmib21crTS0DdH7T1B7wZRWEI89YQAOJMet5yhg==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.15.tgz", + "integrity": "sha512-HFZd2QNQYn1JbIi+Hpd7H+r/lkWxcfIu28nirZ6eCn2LafuvmExMlb/P96Sfx5tf7pPArw39IdhmCF8vmV+NhQ==", "cpu": [ "x64" ], @@ -2076,14 +1673,14 @@ "license": "MIT" }, "node_modules/@shikijs/core": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.4.3.tgz", - "integrity": "sha512-QCR4q2ZO/ILJEuwiBMel4wdcTDb1JGwfjKTxPDF6x8ixOaluPrVqIn06C99AcRPhmYlBR56d/Fb+GN58GzExpg==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.5.0.tgz", + "integrity": "sha512-6CIgwq+bt2JZ3OSjb/nBkkwEf/CfpHcbam+Mg5Pllco7HAGRQ2/EFhZrrJtbyNTgKwknfVS+llsXGygiDGwJWw==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/primitive": "4.4.3", - "@shikijs/types": "4.4.3", + "@shikijs/primitive": "4.5.0", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.5", "hast-util-to-html": "^9.0.5" @@ -2093,13 +1690,13 @@ } }, "node_modules/@shikijs/engine-javascript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.4.3.tgz", - "integrity": "sha512-FbOjFJp9VLdo1Wevs10BBtVxiTWwNLqZh5Gkhjgda/ioL15YOgeSl9n+6XMa3qRlPQzfhFNe641SrynFHYG0nQ==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.5.0.tgz", + "integrity": "sha512-Ed6UdEj84LyYkwnxM5CvSMWAD+id9ExTYri0/+x41U9zrgNifPSS9lZm0JqBP0VfYI8yr8tY5nbNq9+p9R0kFA==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "4.4.3", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.6" }, @@ -2108,13 +1705,13 @@ } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.4.3.tgz", - "integrity": "sha512-EcOQkxdxGQrc1Row/cC2c96/v1dbZqGnEVu1qTuT/MJmp6+cXCvQussowVmCv5Tqr3KuY3c7IbM6HTW3LJ1k9w==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.5.0.tgz", + "integrity": "sha512-dKVmbJecVdB9recl8a/CU4jdpNXyjJQrIcesIkpS70s5HS02ohpnCSpMUbotPnEUzbAcLQ+S4hwZYbkBBiTcJw==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "4.4.3", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2" }, "engines": { @@ -2122,26 +1719,26 @@ } }, "node_modules/@shikijs/langs": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.4.3.tgz", - "integrity": "sha512-ePic0yfAJGOF83D5wBHK/00EjK65oahBYxFk5epgq33WRv7X9UuxLEV8PtR0szC0z8dl7INIpIodB99JRFlR+A==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.5.0.tgz", + "integrity": "sha512-wwBTqwduXSz0X4v9Qa2EWeFaYJEw1clCncWjoRNQRbVDu3SPRTRWucnouYapKj3b8Q+sk/41Vbc4B5c8nuYzLA==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "4.4.3" + "@shikijs/types": "4.5.0" }, "engines": { "node": ">=20" } }, "node_modules/@shikijs/primitive": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.4.3.tgz", - "integrity": "sha512-m0wBeLDQDeIxRdUmrCPdQqfuUamDwRL5isCfYbguKD6NiaKpVbsv+3J81DyIKgNW5h4WAIIr8T4EkgQrBBxvaQ==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.5.0.tgz", + "integrity": "sha512-UM7ShlA8oz0OWxLLO8BmO9Ip6fVqdkt8yF0EH7nOCqHfrx1eEAzF0ZUVK7L+I8NEgeu1PEWSRlxaiPPeCb4iDg==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "4.4.3", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.5" }, @@ -2150,22 +1747,22 @@ } }, "node_modules/@shikijs/themes": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.4.3.tgz", - "integrity": "sha512-w8UHjeUnIR965KMWJHUPXOc2mNJUnK3vpVLYLvw5IYU2mnTTJ89E24OrJDBNiJDQ0qzb0tc4l7mrIXx5cFeIyw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.5.0.tgz", + "integrity": "sha512-zGb87H3UBbpuI4yoh5UguB1XbU+2BDU3kflM7UfZ+Cy2hWo9lBtqjSVK20gmLY6ukYl040hAypGXMgud9vul8Q==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "4.4.3" + "@shikijs/types": "4.5.0" }, "engines": { "node": ">=20" } }, "node_modules/@shikijs/types": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.4.3.tgz", - "integrity": "sha512-UEJxmRR++MAGR6hugn0vgVS2W/6lWAts84FFSrnlH9sP0LNol7E5+NQ792pH8liWUhyMyjhTgSUH3k7iD7tc5g==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.5.0.tgz", + "integrity": "sha512-drtPrtD8N0DENyD2cyt6Ajy+IWsiCLgMxODwLTpvH1UsN6a9jf90tNTPjqwHvA+0Lzu9e0txk8DjfqH1p9UJRw==", "dev": true, "license": "MIT", "dependencies": { @@ -2177,9 +1774,9 @@ } }, "node_modules/@shikijs/vscode-textmate": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", - "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.1.0.tgz", + "integrity": "sha512-cVBuhDQjBZaNMTwBquYfPydrUP+E3hE6oYGasx8h6ZrODIM7/r+gxLDXdd66oszbrggZHEntdE6j+5gYIVyMWQ==", "dev": true, "license": "MIT" }, @@ -2599,9 +2196,9 @@ "license": "ISC" }, "node_modules/@vitejs/plugin-vue": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.9.tgz", - "integrity": "sha512-rD/MORlhaZMlXWW0rEn4FB4wMinWC0z/D7Ye160S5+Rs1mC8ZDAdcDp4SjKfUhG5t8q1ktcPVw4xuTkPRlzrSA==", + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.10.tgz", + "integrity": "sha512-b80aUQh3n+qEzzZm5oQp3rT2QImeCx58K6eFl/RkJ3d65KW0kTuv5lNsLRVAjbW9YRUpo/wzmvzMgV34bTAItA==", "dev": true, "license": "MIT", "dependencies": { @@ -2612,7 +2209,7 @@ }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", - "vue": "^3.2.25" + "vue": "^3.2.25 || ^3.6.0-rc.10" } }, "node_modules/@vue-macros/common": { @@ -2643,16 +2240,16 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.5.43", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.43.tgz", - "integrity": "sha512-zdiLhnbe1QQqgDT8xZMpNmyqZ3qlI+/Q/FHQco57Kwl/b05HhCzN6eVGN9QU9rbga4CrS0H5SYY8VGHZCt/1Hg==", + "version": "3.5.44", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.44.tgz", + "integrity": "sha512-k34nCytbK8PQ1gR2mGROYOw6Pnv/mumqIdrZ3x2tbyXZDWm7ViKGLTfdB+DRrWqEQsLgGJvn0WN9jBif5zCTLQ==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.8", - "@vue/shared": "3.5.43", + "@babel/parser": "^7.29.9", + "@vue/shared": "3.5.44", "entities": "^7.0.1", "estree-walker": "^2.0.2", - "source-map-js": "^1.2.1" + "source-map-js": "^1.2.2" } }, "node_modules/@vue/compiler-core/node_modules/entities": { @@ -2674,30 +2271,30 @@ "license": "MIT" }, "node_modules/@vue/compiler-dom": { - "version": "3.5.43", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.43.tgz", - "integrity": "sha512-PEZoAk3NQmsn/ejMzSOCyTYqwGqczrWm70PuhBKjjv1+TCoQAaO/zOqNwjV+honlNstT5ILxtc+8r8UUfj+iEQ==", + "version": "3.5.44", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.44.tgz", + "integrity": "sha512-W5AoBFWdw1lQAKiHowkfgFKFab82oSRT6sGsPfw/q1GRjsy/ZJFLHGhJyBRIFN9APLTUduDH9U2JAiPOIyKuYg==", "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.43", - "@vue/shared": "3.5.43" + "@vue/compiler-core": "3.5.44", + "@vue/shared": "3.5.44" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.43", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.43.tgz", - "integrity": "sha512-FCbrG3XNCRl+js3huuKx4IVHBLTvMkJhVepjbxSPu1gn4yWLaYtGNQdjJGZaMytXB6qb76qQDDmDSLy/vkmleQ==", + "version": "3.5.44", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.44.tgz", + "integrity": "sha512-dzHmQ4jXTpdr5FjIQUeykVakN/uzqFbUo9/C5ikBFg3a3PeM6uRxeczx1ZbXBML0/zJstEh3ygYipzR5Z7b2Pw==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.8", - "@vue/compiler-core": "3.5.43", - "@vue/compiler-dom": "3.5.43", - "@vue/compiler-ssr": "3.5.43", - "@vue/shared": "3.5.43", + "@babel/parser": "^7.29.9", + "@vue/compiler-core": "3.5.44", + "@vue/compiler-dom": "3.5.44", + "@vue/compiler-ssr": "3.5.44", + "@vue/shared": "3.5.44", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", - "postcss": "^8.5.28", - "source-map-js": "^1.2.1" + "postcss": "^8.5.29", + "source-map-js": "^1.2.2" } }, "node_modules/@vue/compiler-sfc/node_modules/estree-walker": { @@ -2716,13 +2313,13 @@ } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.43", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.43.tgz", - "integrity": "sha512-GF62orf7KiJX9RqrHNGrYBudsQGD0OhJ5nDs90O8UiDuS40+YMYomiXu6w6EuvtXuRDc3MSNis3EaaSKAVSWpg==", + "version": "3.5.44", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.44.tgz", + "integrity": "sha512-xr5gb1JVHlfXJwSlRz1FeP6uxoazdzHuMTVLE7up+4Vrqxk219CvxLPxD9NXBt47yvZW7+p4DXfyp4O1fkByIA==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.43", - "@vue/shared": "3.5.43" + "@vue/compiler-dom": "3.5.44", + "@vue/shared": "3.5.44" } }, "node_modules/@vue/devtools-api": { @@ -2753,57 +2350,57 @@ "license": "MIT" }, "node_modules/@vue/reactivity": { - "version": "3.5.43", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.43.tgz", - "integrity": "sha512-G/c9GyOZNI2jVaaS6OX1EF1SSFSv7H0ERqNTl4+DTFMlZmB5eVAB53aLQNam/7NL2NPtaDD7RdVrzf8uJzMuOA==", + "version": "3.5.44", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.44.tgz", + "integrity": "sha512-u+QJdKeBBEADkPdevsL+6E12QlYVfBD8Zcw5qjDQKtamI6l14KyqazJMobhCKelhWN5zpyKUiEDoTyHE93cqWw==", "license": "MIT", "dependencies": { - "@vue/shared": "3.5.43" + "@vue/shared": "3.5.44" } }, "node_modules/@vue/runtime-core": { - "version": "3.5.43", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.43.tgz", - "integrity": "sha512-hU6U6VnVhBGQDpvlnnDlIB8ZGJBiOcgk2lh/0InltHiz3D8oSkluvuvY+do1G2H3+udeKFsmaBlgVYP7gXQzEw==", + "version": "3.5.44", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.44.tgz", + "integrity": "sha512-uEa/ndwjhrrhnOfb2p+sZy6zeoamJOISqaLSJGk/8R6nABT1ZldpzcJoPzKj+zHVomVBPcmQYyC2r4LtvDV6CQ==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.43", - "@vue/shared": "3.5.43" + "@vue/reactivity": "3.5.44", + "@vue/shared": "3.5.44" } }, "node_modules/@vue/runtime-dom": { - "version": "3.5.43", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.43.tgz", - "integrity": "sha512-Bb2Jc0YjjJdMt1SJmb9b2L/IWd3I8lIT9x9eS/xvvP9CiVgna0ffua74xKRmt4/uSJ+0r4iN8ex1jrqkhQGWQw==", + "version": "3.5.44", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.44.tgz", + "integrity": "sha512-3fc4ARcXVhVBaJ3ujWiNZJARD6pkyRcwG+ZYhMzjKtKUp7MAY0HLwr7r3Smep3Li6ZaWT6ewdmx8XqdaD5oNZg==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.43", - "@vue/runtime-core": "3.5.43", - "@vue/shared": "3.5.43", + "@vue/reactivity": "3.5.44", + "@vue/runtime-core": "3.5.44", + "@vue/shared": "3.5.44", "csstype": "^3.2.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.5.43", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.43.tgz", - "integrity": "sha512-l2Ygjv9NehV94PSBxNWsAHC0j/eIIKbn92mBuWXAPGLnn6HfJ6MH5ubsd+Nk0YoZ5FRuxWI1P2VSoh+dbPQhCQ==", + "version": "3.5.44", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.44.tgz", + "integrity": "sha512-R4S1UoH4h5Frrauv8Z5XE5TxV9oBiUSgWIC4TyVK1FK+RocRnOLwFA5Xcmo2011RlgJp+AbZCnw6afrhlgRuUQ==", "license": "MIT", "dependencies": { - "@vue/compiler-ssr": "3.5.43", - "@vue/runtime-dom": "3.5.43", - "@vue/shared": "3.5.43" + "@vue/compiler-ssr": "3.5.44", + "@vue/runtime-dom": "3.5.44", + "@vue/shared": "3.5.44" } }, "node_modules/@vue/shared": { - "version": "3.5.43", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.43.tgz", - "integrity": "sha512-uksS7YGMR5NZyr4JNq0Rp+QyLns0ueaz20KwzIPW9R0LH1Vnt4E+XUM29PNseEbf1www2gOuhuDi5AKOIXag9Q==", + "version": "3.5.44", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.44.tgz", + "integrity": "sha512-H82XLH0DjmSOdbEwO15x3QTo1f5PWEtv237eLpYKc0mqLu+B8hnq16lFWmuBmNurkeiG3wr+oM1FhOll/YVFRg==", "license": "MIT" }, "node_modules/acorn": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", - "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.19.0.tgz", + "integrity": "sha512-oJlA3XiRm7Cyk6qFD2Jn8ak9B7jSy0qy00ADO3+8dpT0LSjFihQYv4C02LFCSYJV3Q37xYwwRy5m+IpIiUzqWw==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -2990,16 +2587,16 @@ } }, "node_modules/astro": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/astro/-/astro-7.3.7.tgz", - "integrity": "sha512-MyxnNzy+HHkLa8iNVcGTXbmSTlkjqkXJyRcMU3EwprbsF7gh3M03DKLAGVcVTmATF8jV1Fen0rkala1JiEyMSg==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/astro/-/astro-7.4.2.tgz", + "integrity": "sha512-FAH4cdDlFaVnQGjazLTEIC5vJqGlo5XANc1wIbzQHIqAjJTll/RWTUs+SPNW1JdezG4YGxMZllaE5A41T2kzhA==", "dev": true, "license": "MIT", "dependencies": { "@astrojs/compiler-rs": "^0.5.1", - "@astrojs/internal-helpers": "0.12.0", - "@astrojs/markdown-satteri": "0.4.3", - "@astrojs/telemetry": "3.3.3", + "@astrojs/internal-helpers": "0.13.0", + "@astrojs/markdown-satteri": "0.4.5", + "@astrojs/telemetry": "3.4.1", "@capsizecss/unpack": "^4.0.1", "@clack/prompts": "^1.8.1", "@oslojs/encoding": "^1.1.0", @@ -3010,51 +2607,50 @@ "clsx": "^2.1.1", "common-ancestor-path": "^2.0.0", "cookie": "^2.0.1", - "devalue": "^5.9.4", + "devalue": "^6.0.2", "diff": "^9.0.0", "dset": "^3.1.4", - "es-module-lexer": "^3.0.2", - "esbuild": "^0.28.0", - "find-proc": "0.2.0", + "es-module-lexer": "^3.0.3", "flattie": "^1.1.1", "fontace": "~0.4.1", "get-tsconfig": "5.0.0-beta.6", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", - "http-cache-semantics": "^4.2.0", + "http-cache-semantics": "^4.3.0", "jsonc-parser": "^3.3.1", - "magic-string": "^1.4.2", + "magic-string": "^1.4.3", "magicast": "^0.5.5", "mrmime": "^2.0.1", "neotraverse": "^1.0.1", "obug": "^3.0.0", "p-limit": "^7.3.3", - "p-queue": "^9.3.3", - "package-manager-detector": "^1.8.0", + "p-queue": "^9.3.5", + "package-manager-detector": "^1.9.0", "piccolore": "^0.1.3", "picomatch": "^4.0.7", - "rolldown": "^1.2.11", - "shiki": "^4.4.3", - "smol-toml": "^1.9.0", + "rolldown": "^1.2.13", + "shiki": "^4.5.0", + "smol-toml": "1.9.1", "svgo": "^4.1.0", "tinyclip": "^1.0.3", "tinyexec": "^1.3.1", "tinyglobby": "^0.2.17", + "tinyps": "^0.5.0", "ultrahtml": "^1.7.0", - "unifont": "~0.7.5", + "unifont": "^1.0.3", "unstorage": "^1.17.5", "verkit": "^0.5.0", - "vite": "^8.3.1", + "vite": "^8.3.4", "vitefu": "^1.1.3", "xxhash-wasm": "^1.1.0", "yargs-parser": "^22.0.0", - "zod": "^4.6.5" + "zod": "^4.6.6" }, "bin": { "astro": "bin/astro.mjs" }, "engines": { - "node": ">=22.12.0", + "node": ">=22.23.4", "npm": ">=9.6.5", "pnpm": ">=7.1.0" }, @@ -3075,9 +2671,9 @@ } }, "node_modules/axe-core": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.13.0.tgz", - "integrity": "sha512-UzGt8zg7Ny8djbYMhxl2zuEevVa7r2gJjYY5Lwr1xM7+XU2nd6CkIWFTVcCIbAP63vSz71NaVyyuSk9lHKcy0A==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.14.0.tgz", + "integrity": "sha512-9WTZxEjsZ7b13TH8JPmbV2z8CHbl80/2hm3XPEG4JgNdQLK81IBRXmSxHfMAOkSqQeRxT/0dwNDz2GOm3zzpcQ==", "dev": true, "license": "MPL-2.0", "engines": { @@ -3459,11 +3055,14 @@ } }, "node_modules/devalue": { - "version": "5.9.4", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.9.4.tgz", - "integrity": "sha512-sPAT4pztbu6586/hrhOnMKS17IJrvg12mXiSPSS3W5qDeN2RGgvZ0diZCm31dBbnevfVmujNO3IM2wrS4Y2Rhg==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-6.0.3.tgz", + "integrity": "sha512-3woMEITftG1wKeO/4d/QXH1DVKctTSZg3jNGPpjp9hNr5Hos8MCFF5McTML5ZtgKDObm2R591B0spRp2IVernA==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/devlop": { "version": "1.1.0", @@ -3572,9 +3171,9 @@ } }, "node_modules/es-module-lexer": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-3.0.3.tgz", - "integrity": "sha512-yWGe1O/j+almnV4hOYrmZo8u58JdnmXEMneRQAYkWtqSiT86yoMIEKF4rpqEDj52tbYl3xceBD3DQIBwcsC9Pw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-3.0.4.tgz", + "integrity": "sha512-BldNY5mwkVu+cQ5Ymn3e6hB9Sx8XHx4ZevWbiUyZbfKxJxYO27Hf0wfzkxIaD5CAJMaGl3YspKELj0ff/7nCMA==", "dev": true, "license": "MIT" }, @@ -3612,48 +3211,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/esbuild": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", - "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", - "devOptional": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.2", - "@esbuild/android-arm": "0.28.2", - "@esbuild/android-arm64": "0.28.2", - "@esbuild/android-x64": "0.28.2", - "@esbuild/darwin-arm64": "0.28.2", - "@esbuild/darwin-x64": "0.28.2", - "@esbuild/freebsd-arm64": "0.28.2", - "@esbuild/freebsd-x64": "0.28.2", - "@esbuild/linux-arm": "0.28.2", - "@esbuild/linux-arm64": "0.28.2", - "@esbuild/linux-ia32": "0.28.2", - "@esbuild/linux-loong64": "0.28.2", - "@esbuild/linux-mips64el": "0.28.2", - "@esbuild/linux-ppc64": "0.28.2", - "@esbuild/linux-riscv64": "0.28.2", - "@esbuild/linux-s390x": "0.28.2", - "@esbuild/linux-x64": "0.28.2", - "@esbuild/netbsd-arm64": "0.28.2", - "@esbuild/netbsd-x64": "0.28.2", - "@esbuild/openbsd-arm64": "0.28.2", - "@esbuild/openbsd-x64": "0.28.2", - "@esbuild/openharmony-arm64": "0.28.2", - "@esbuild/sunos-x64": "0.28.2", - "@esbuild/win32-arm64": "0.28.2", - "@esbuild/win32-ia32": "0.28.2", - "@esbuild/win32-x64": "0.28.2" - } - }, "node_modules/escape-string-regexp": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", @@ -3835,16 +3392,6 @@ "dev": true, "license": "MIT" }, - "node_modules/find-proc": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/find-proc/-/find-proc-0.2.0.tgz", - "integrity": "sha512-a6h2nTrgB3g5Wrn4au9Ux4kMk7IJtyF6oA8uGn+mk3weLZssUtc1cp6meHIzzuW2o1srrBAxzkmXLbqjRkgB6w==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, "node_modules/flattie": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz", @@ -3855,6 +3402,13 @@ "node": ">=8" } }, + "node_modules/fnv1a-64": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/fnv1a-64/-/fnv1a-64-0.1.2.tgz", + "integrity": "sha512-mJbcILTPybAR1jdOwt/lVv8N2cffeJFFP+gVbSAwLEx1ujXH27RpPd8Rokec/KX9c76UYIB6Co+H4lQzxPnJfA==", + "dev": true, + "license": "MIT" + }, "node_modules/fontace": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.4.1.tgz", @@ -6024,13 +5578,6 @@ "ufo": "^1.6.1" } }, - "node_modules/ohash": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.12.tgz", - "integrity": "sha512-65S/5gk9YSsaRjcyf7Nfa6h/d3E8/1gslpXfI4W7Dxn/oap8IKRuNT5VXkLQ1YFKIEg4apRY4Pj6aiwFzrDdmw==", - "dev": true, - "license": "MIT" - }, "node_modules/oniguruma-parser": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.2.tgz", @@ -6067,9 +5614,9 @@ } }, "node_modules/p-queue": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.3.tgz", - "integrity": "sha512-NXAOdnEe5FsZJfT4oK84lE1Y5cFFdWlRuOo5tww8DyNMxyRXwn39fIkUtNLKppcPC+UYU/bXujNCUGDv01y7CA==", + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.5.tgz", + "integrity": "sha512-Lki/zhXFVmDhesBUn/yHRLW9Bte7mE7xoFHzTR8sIomV7a2z+LxYAPkGvdfidNiu4fKSfjtawixxSHcZci5QcQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6084,9 +5631,9 @@ } }, "node_modules/p-timeout": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.1.tgz", - "integrity": "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.2.tgz", + "integrity": "sha512-prbX4Z3YszrFNgH+MW5Zoeq3baXrMtP/MQnFeET90UB/GtGcGDQ5Usg9OCy6ETjTTntOw1SL2z9fMPUppN3Guw==", "dev": true, "license": "MIT", "engines": { @@ -6097,9 +5644,9 @@ } }, "node_modules/package-manager-detector": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.8.0.tgz", - "integrity": "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.9.0.tgz", + "integrity": "sha512-zAMfbta9nPA8AKkA4WdmNAT8R8s6Dk0/xwPsqNnRidMFcLo1YkLuPDTgs2f64XdzS8vbLNnoJ+uUIkgbz7oRHA==", "dev": true, "license": "MIT" }, @@ -6224,13 +5771,13 @@ } }, "node_modules/playwright": { - "version": "1.64.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.64.0.tgz", - "integrity": "sha512-kVzTnYFYEyQ9RGzBjNCd2+yEqWmVbxl3AHPynv3qQ6JTjv4a+kwRcnqQwIpuP3NnrnIrE/Q6wWAIAvMfIE2/Yg==", + "version": "1.64.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.64.1.tgz", + "integrity": "sha512-HCrVhHr5QQuwYoswEUGTb7gGp522yflbv/ST8nF4sFWGuLjQCt17Q/EubpGGSNKYn1tsTCPZxqHhHCfVURu7UA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.64.0" + "playwright-core": "1.64.1" }, "bin": { "playwright": "cli.js" @@ -6240,9 +5787,9 @@ } }, "node_modules/playwright-core": { - "version": "1.64.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.64.0.tgz", - "integrity": "sha512-T9r+MZkTECl2+oUcZ26YgZzTrYidTsIhYYkJix+6iDOymOb1FB2RLLSOxRGnZGv5DStt+aduIVbt+E8WygXYpg==", + "version": "1.64.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.64.1.tgz", + "integrity": "sha512-BC4s8y6SEVA6Q1rSxZTto8hI1KUI3xXlHGZgvGqP4IqPdI/a6FX9H29IDNz7vKo9l21b6LfYosScPL6M3xxyDQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -6253,9 +5800,9 @@ } }, "node_modules/postcss": { - "version": "8.5.29", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.29.tgz", - "integrity": "sha512-49cGhUbXj8Qenv0iTMxA1cFBzxXoctpC9Ujd77t1WcbJIr6nF/eI7g/8MgxrYldFRuAXvja7xQRwavoW7kgrxQ==", + "version": "8.5.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.31.tgz", + "integrity": "sha512-YUbWYCgErwnMAVkjUnYa+KlMBzGpHwiIt/DE7f0G33AuX2LH9UcTk6KgWxd3zRU+pN3u/C+Xl3EnMLM4Hea7Sg==", "funding": [ { "type": "opencollective", @@ -6272,7 +5819,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.19", + "nanoid": "^3.3.20", "picocolors": "^1.1.1", "source-map-js": "^1.2.2" }, @@ -6342,9 +5889,9 @@ "license": "MIT" }, "node_modules/react": { - "version": "19.3.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.3.0.tgz", - "integrity": "sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==", + "version": "19.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-19.3.1.tgz", + "integrity": "sha512-QNhWdt7nrgVWWQG58QuGsAR3jv3Hbe4mb4vz7w2csnHavciZJgda1CPNaldF6eVxv90ud3jUXpKlHL69gO38yw==", "dev": true, "license": "MIT", "engines": { @@ -6352,16 +5899,16 @@ } }, "node_modules/react-dom": { - "version": "19.3.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.3.0.tgz", - "integrity": "sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q==", + "version": "19.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.3.1.tgz", + "integrity": "sha512-Y0bARz53lhEC1NMCASs0/j+faB/zqt3R8hpvg1e8+61ZVJ4UL0UdC4cBbXfZMcIuhrfgeILTLe+ZeBCavQPtKQ==", "dev": true, "license": "MIT", "dependencies": { "scheduler": "^0.28.0" }, "peerDependencies": { - "react": "^19.3.0" + "react": "^19.3.1" } }, "node_modules/readdirp": { @@ -6700,13 +6247,13 @@ } }, "node_modules/rolldown": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.13.tgz", - "integrity": "sha512-/5apOkwWxtACcQtZ5WlrAsKS4JwXVThQPJZ3RqIruRY9UG9M8e0VlXN068xum/JRKA4aIUoJ13ghe/kGCvidiQ==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.15.tgz", + "integrity": "sha512-6odND+fel5zVw3I4Yc2e69gvguDnX0CAAGiNDZSq4ik5WUcaLrkD2GLuog0XcODbor31hZ5ayEMgVDno+KPV5g==", "devOptional": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.153.0", + "@oxc-project/types": "=0.155.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -6716,21 +6263,21 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm-eabi": "1.2.13", - "@rolldown/binding-android-arm64": "1.2.13", - "@rolldown/binding-darwin-arm64": "1.2.13", - "@rolldown/binding-darwin-x64": "1.2.13", - "@rolldown/binding-freebsd-x64": "1.2.13", - "@rolldown/binding-linux-arm-gnueabihf": "1.2.13", - "@rolldown/binding-linux-arm64-gnu": "1.2.13", - "@rolldown/binding-linux-arm64-musl": "1.2.13", - "@rolldown/binding-linux-ppc64-gnu": "1.2.13", - "@rolldown/binding-linux-s390x-gnu": "1.2.13", - "@rolldown/binding-linux-x64-gnu": "1.2.13", - "@rolldown/binding-linux-x64-musl": "1.2.13", - "@rolldown/binding-openharmony-arm64": "1.2.13", - "@rolldown/binding-win32-arm64-msvc": "1.2.13", - "@rolldown/binding-win32-x64-msvc": "1.2.13" + "@rolldown/binding-android-arm-eabi": "1.2.15", + "@rolldown/binding-android-arm64": "1.2.15", + "@rolldown/binding-darwin-arm64": "1.2.15", + "@rolldown/binding-darwin-x64": "1.2.15", + "@rolldown/binding-freebsd-x64": "1.2.15", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.15", + "@rolldown/binding-linux-arm64-gnu": "1.2.15", + "@rolldown/binding-linux-arm64-musl": "1.2.15", + "@rolldown/binding-linux-ppc64-gnu": "1.2.15", + "@rolldown/binding-linux-s390x-gnu": "1.2.15", + "@rolldown/binding-linux-x64-gnu": "1.2.15", + "@rolldown/binding-linux-x64-musl": "1.2.15", + "@rolldown/binding-openharmony-arm64": "1.2.15", + "@rolldown/binding-win32-arm64-msvc": "1.2.15", + "@rolldown/binding-win32-x64-msvc": "1.2.15" } }, "node_modules/satteri": { @@ -6846,18 +6393,18 @@ } }, "node_modules/shiki": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.4.3.tgz", - "integrity": "sha512-Mb/GvXPHBAXdgGIcnfU5L3ldpn1XcxrGkPHwqgRx17/I2XRfqlFKk2vGkHWINn1kdXvzJZeuO3is6I9KLPFm0g==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.5.0.tgz", + "integrity": "sha512-OcRW72ngQvc+MSVWBRIovC/BTW589iUE/Vxav7VeM4RcY9MUjqB+IR6ILG1k9nuW6LiG/nct9uma4/MBtnZbmQ==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/core": "4.4.3", - "@shikijs/engine-javascript": "4.4.3", - "@shikijs/engine-oniguruma": "4.4.3", - "@shikijs/langs": "4.4.3", - "@shikijs/themes": "4.4.3", - "@shikijs/types": "4.4.3", + "@shikijs/core": "4.5.0", + "@shikijs/engine-javascript": "4.5.0", + "@shikijs/engine-oniguruma": "4.5.0", + "@shikijs/langs": "4.5.0", + "@shikijs/themes": "4.5.0", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.5" }, @@ -6894,9 +6441,9 @@ } }, "node_modules/smol-toml": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.9.0.tgz", - "integrity": "sha512-hpd+HLON7HdZXqYchMM/+LaTTbdK0AU3NngIJ4KVyWbY9bfQqdL9cD+4yf6dUoU2Ap4VsU0JkQi6FxAI1B2mXQ==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.9.1.tgz", + "integrity": "sha512-j7WyPdf0CJoutMzMoPLF/bVXHtKZIT9Rb4eGeEbWw8X2t5oirjPgpL+OpaENZrILYaXqYwnVH+qgUwVbl+pUJQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -6951,6 +6498,13 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/std-env": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.3.0.tgz", + "integrity": "sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==", + "dev": true, + "license": "MIT" + }, "node_modules/store2": { "version": "2.14.4", "resolved": "https://registry.npmjs.org/store2/-/store2-2.14.4.tgz", @@ -7083,6 +6637,13 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/tinyps": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/tinyps/-/tinyps-0.5.1.tgz", + "integrity": "sha512-B6Ykif5HflC3AdDkS4Zst/2muYVfeXoVMy+KorqH80s/1x4vunIORpNySH681X7fjj+dFM9MDKD6/Hsccjb87Q==", + "dev": true, + "license": "MIT" + }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -7169,9 +6730,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/undici/-/undici-8.10.2.tgz", - "integrity": "sha512-/y4/bH9YNU5hi9NIrpOuvGXFcxrj3CMrV+/AYpowAYTpHn8gX/XPFjNy766FPoYY0miQhdW977JFWKGNhBdwyQ==", + "version": "8.12.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-8.12.3.tgz", + "integrity": "sha512-+fdndUTwBP86cVjihTp21hZHo7d6oj1c/47XPA3lL8mM0XHs+C4EkcjmgRsFnFk2f/UONGDy9ItBItmXsLOQHw==", "dev": true, "license": "MIT", "engines": { @@ -7199,14 +6760,15 @@ } }, "node_modules/unifont": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.7.5.tgz", - "integrity": "sha512-ULe/Cs+ZIsq+dcFofNkhqielCrUJnb5mr+Yc4EBM2VlL+6OZR6+cjtI2mT1bJvRBrVncqHAbLURxmPLcCXzWMg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/unifont/-/unifont-1.0.3.tgz", + "integrity": "sha512-XGnEwj5sWdCbiBX01mWLSBncS0yMRjnLygau3IfdOlfjMacNIQvTGW4VH7pWBq+gGWArfSef/CensMLjMmIr/A==", "dev": true, "license": "MIT", "dependencies": { "css-tree": "^3.1.0", - "ohash": "^2.0.11", + "fnv1a-64": "^0.1.2", + "std-env": "^4.2.0", "undici": "^8.0.0" } }, @@ -7586,16 +7148,16 @@ } }, "node_modules/vite": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.3.tgz", - "integrity": "sha512-cTAldKPImjg6c+gk48U19POPn3GCBzZwpdsN8ZMEEcbpes+6/wvfqUd0C2y3qYY4wsj8PwgFwrZ/1jBPVttMSg==", + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.5.tgz", + "integrity": "sha512-z1YpjieJ9g0ebTmQpLBv/oq9E3F9EIlOe+7LahW8SrE3LTiG3udBRUXQOlYXP9b+IC2q2phHeVxj9xGlw34OEQ==", "devOptional": true, "license": "MIT", "dependencies": { "lightningcss": "^1.33.0", "picomatch": "^4.0.7", - "postcss": "^8.5.28", - "rolldown": "~1.2.11", + "postcss": "^8.5.30", + "rolldown": "~1.2.14", "tinyglobby": "^0.2.17" }, "bin": { @@ -7612,7 +7174,7 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.7.1", + "@vitejs/devtools": "^0.7.1 || ^0.8.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", @@ -7684,16 +7246,16 @@ } }, "node_modules/vue": { - "version": "3.5.43", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.43.tgz", - "integrity": "sha512-o5qZoksdnjIKvW1srZ3ab7pcDNYAerBjRe54D0LBLfRdCYFrSgBHVXokMas35czQc0//lmx4/tuY4ZNQ+Rf2Ng==", + "version": "3.5.44", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.44.tgz", + "integrity": "sha512-dvvmaOCG7lAMkJTPqPwWeGMsPS6DIsFsfZDUgBp9V6mHf9b3+/wyVwYR4Es+WV6uJC0FKRxp81Obcq0ZwUcGFQ==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.43", - "@vue/compiler-sfc": "3.5.43", - "@vue/runtime-dom": "3.5.43", - "@vue/server-renderer": "3.5.43", - "@vue/shared": "3.5.43" + "@vue/compiler-dom": "3.5.44", + "@vue/compiler-sfc": "3.5.44", + "@vue/runtime-dom": "3.5.44", + "@vue/server-renderer": "3.5.44", + "@vue/shared": "3.5.44" }, "peerDependencies": { "typescript": "*" @@ -7828,9 +7390,9 @@ } }, "node_modules/zod": { - "version": "4.6.5", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.5.tgz", - "integrity": "sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q==", + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.7.tgz", + "integrity": "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==", "dev": true, "license": "MIT", "funding": { diff --git a/package.json b/package.json index 963654156..85e366615 100644 --- a/package.json +++ b/package.json @@ -48,26 +48,26 @@ "telegram:publish": "node ports/telegram/publish.mjs" }, "devDependencies": { - "@astrojs/markdown-remark": "7.3.2", - "@axe-core/playwright": "4.13.0", - "@playwright/test": "1.64.0", - "@vitejs/plugin-vue": "6.0.9", - "astro": "7.3.7", - "es-module-lexer": "3.0.3", + "@astrojs/markdown-remark": "7.3.4", + "@axe-core/playwright": "4.14.0", + "@playwright/test": "1.64.1", + "@vitejs/plugin-vue": "6.0.10", + "astro": "7.4.2", + "es-module-lexer": "3.0.4", "fflate": "0.8.3", "jsonc-parser": "3.3.1", "parse5": "8.0.1", - "postcss": "8.5.29", + "postcss": "8.5.31", "postcss-value-parser": "4.2.0", - "react": "19.3.0", - "react-dom": "19.3.0", - "smol-toml": "1.9.0", + "react": "19.3.1", + "react-dom": "19.3.1", + "smol-toml": "1.9.1", "teleproto": "1.229.1", "typescript": "7.0.2", - "vite": "8.3.3", - "vue": "3.5.43", + "vite": "8.3.5", + "vue": "3.5.44", "yaml": "2.9.1", - "zod": "4.6.5" + "zod": "4.6.7" }, "workspaces": [ "packages/ui", From 2ba2eea59c31b1d0cc3e2e3c5224261befc3ddc4 Mon Sep 17 00:00:00 2001 From: j3w1 Date: Mon, 2 Nov 2026 23:37:39 +0800 Subject: [PATCH 2/2] fix: restore explicit build dependency and accessible search hint --- package-lock.json | 459 +++++++++ package.json | 1 + ...anced-CqBF0dSb.js => advanced-BrFnVc0y.js} | 7 +- .../choice-DqwWT5pJ.js} | 9 +- .../compositions-DWG4tv9E.js} | 7 +- .../display-l54fb8vw.js} | 5 +- .../element-DcrNU9Wh.js} | 5 +- ...r-BvWZCBPR.js => form-builder-CkeTBQe-.js} | 12 +- .../form-builder-DbZUZMo1.js} | 8 +- ...-BKRLylvq.js => form-workflow-B183Y5gc.js} | 424 ++++---- .../forms-C3u5121t.js} | 5 +- .../markup-AopKpwOF.js} | 3 +- .../native-D61761VL.js} | 5 +- .../navigation-CknoksQ5.js} | 5 +- .../overlays-BW66WXLm.js} | 5 +- .../tables-zo8ebTOo.js} | 5 +- packages/ui/dist/components/admin-form.js | 9 +- packages/ui/dist/components/alert.js | 9 +- packages/ui/dist/components/avatar.js | 9 +- packages/ui/dist/components/badge.js | 9 +- packages/ui/dist/components/breadcrumbs.js | 9 +- packages/ui/dist/components/button-group.js | 9 +- packages/ui/dist/components/button.js | 9 +- packages/ui/dist/components/card.js | 9 +- packages/ui/dist/components/chart.js | 9 +- packages/ui/dist/components/checkbox.js | 9 +- packages/ui/dist/components/chip.js | 9 +- packages/ui/dist/components/code-editor.js | 9 +- packages/ui/dist/components/combobox.js | 9 +- .../ui/dist/components/command-palette.js | 9 +- .../ui/dist/components/compact-dashboard.js | 9 +- packages/ui/dist/components/data-table.js | 9 +- packages/ui/dist/components/date-picker.js | 9 +- .../ui/dist/components/description-list.js | 9 +- packages/ui/dist/components/diagnostics.js | 9 +- packages/ui/dist/components/dialog.js | 9 +- packages/ui/dist/components/diff-view.js | 9 +- packages/ui/dist/components/disclosure.js | 9 +- packages/ui/dist/components/drawer.js | 9 +- packages/ui/dist/components/editor-search.js | 9 +- packages/ui/dist/components/empty-state.js | 9 +- packages/ui/dist/components/error-state.js | 9 +- packages/ui/dist/components/field.js | 9 +- packages/ui/dist/components/fieldset.js | 9 +- packages/ui/dist/components/file-browser.js | 9 +- packages/ui/dist/components/file-input.js | 9 +- .../ui/dist/components/filterable-table.js | 9 +- packages/ui/dist/components/form-builder.js | 2 +- .../ui/dist/components/i3-window-frame.js | 9 +- packages/ui/dist/components/icon-button.js | 9 +- packages/ui/dist/components/kbd.js | 9 +- packages/ui/dist/components/link.js | 9 +- packages/ui/dist/components/list.js | 9 +- .../ui/dist/components/loading-indicator.js | 9 +- packages/ui/dist/components/menu.js | 9 +- packages/ui/dist/components/multiselect.js | 9 +- packages/ui/dist/components/number-field.js | 9 +- packages/ui/dist/components/pagination.js | 9 +- packages/ui/dist/components/popover.js | 9 +- packages/ui/dist/components/progress.js | 9 +- packages/ui/dist/components/radio-group.js | 9 +- packages/ui/dist/components/range.js | 9 +- packages/ui/dist/components/repeater.js | 9 +- packages/ui/dist/components/search-field.js | 9 +- .../ui/dist/components/segmented-control.js | 9 +- packages/ui/dist/components/select.js | 9 +- packages/ui/dist/components/settings-panel.js | 9 +- packages/ui/dist/components/sidebar-nav.js | 9 +- packages/ui/dist/components/skeleton.js | 9 +- packages/ui/dist/components/skip-link.js | 9 +- packages/ui/dist/components/switch.js | 9 +- packages/ui/dist/components/table.js | 9 +- packages/ui/dist/components/tabs.js | 9 +- packages/ui/dist/components/terminal.js | 9 +- packages/ui/dist/components/text-field.js | 9 +- packages/ui/dist/components/textarea.js | 9 +- packages/ui/dist/components/time-picker.js | 9 +- packages/ui/dist/components/timeline.js | 9 +- packages/ui/dist/components/toast.js | 9 +- packages/ui/dist/components/toolbar.js | 9 +- packages/ui/dist/components/tooltip.js | 9 +- packages/ui/dist/components/tree.js | 9 +- packages/ui/dist/components/wizard.js | 9 +- packages/ui/dist/contracts/admin-form.json | 2 +- packages/ui/dist/contracts/alert.json | 2 +- packages/ui/dist/contracts/avatar.json | 2 +- packages/ui/dist/contracts/badge.json | 2 +- packages/ui/dist/contracts/breadcrumbs.json | 2 +- packages/ui/dist/contracts/button-group.json | 2 +- packages/ui/dist/contracts/button.json | 2 +- packages/ui/dist/contracts/card.json | 2 +- packages/ui/dist/contracts/chart.json | 2 +- packages/ui/dist/contracts/checkbox.json | 2 +- packages/ui/dist/contracts/chip.json | 2 +- packages/ui/dist/contracts/code-editor.json | 2 +- packages/ui/dist/contracts/combobox.json | 2 +- .../ui/dist/contracts/command-palette.json | 2 +- .../ui/dist/contracts/compact-dashboard.json | 2 +- packages/ui/dist/contracts/data-table.json | 2 +- packages/ui/dist/contracts/date-picker.json | 2 +- .../ui/dist/contracts/description-list.json | 2 +- packages/ui/dist/contracts/diagnostics.json | 2 +- packages/ui/dist/contracts/dialog.json | 2 +- packages/ui/dist/contracts/diff-view.json | 2 +- packages/ui/dist/contracts/disclosure.json | 2 +- packages/ui/dist/contracts/drawer.json | 2 +- packages/ui/dist/contracts/editor-search.json | 2 +- packages/ui/dist/contracts/empty-state.json | 2 +- packages/ui/dist/contracts/error-state.json | 2 +- packages/ui/dist/contracts/field.json | 2 +- packages/ui/dist/contracts/fieldset.json | 2 +- packages/ui/dist/contracts/file-browser.json | 2 +- packages/ui/dist/contracts/file-input.json | 2 +- .../ui/dist/contracts/filterable-table.json | 2 +- packages/ui/dist/contracts/form-builder.json | 2 +- .../ui/dist/contracts/i3-window-frame.json | 2 +- packages/ui/dist/contracts/icon-button.json | 2 +- packages/ui/dist/contracts/kbd.json | 2 +- packages/ui/dist/contracts/link.json | 2 +- packages/ui/dist/contracts/list.json | 2 +- .../ui/dist/contracts/loading-indicator.json | 2 +- packages/ui/dist/contracts/menu.json | 2 +- packages/ui/dist/contracts/multiselect.json | 2 +- packages/ui/dist/contracts/number-field.json | 2 +- packages/ui/dist/contracts/pagination.json | 2 +- packages/ui/dist/contracts/popover.json | 2 +- packages/ui/dist/contracts/progress.json | 2 +- packages/ui/dist/contracts/radio-group.json | 2 +- packages/ui/dist/contracts/range.json | 2 +- packages/ui/dist/contracts/repeater.json | 2 +- packages/ui/dist/contracts/search-field.json | 2 +- .../ui/dist/contracts/segmented-control.json | 2 +- packages/ui/dist/contracts/select.json | 2 +- .../ui/dist/contracts/settings-panel.json | 2 +- packages/ui/dist/contracts/sidebar-nav.json | 2 +- packages/ui/dist/contracts/skeleton.json | 2 +- packages/ui/dist/contracts/skip-link.json | 2 +- packages/ui/dist/contracts/switch.json | 2 +- packages/ui/dist/contracts/table.json | 2 +- packages/ui/dist/contracts/tabs.json | 2 +- packages/ui/dist/contracts/terminal.json | 2 +- packages/ui/dist/contracts/text-field.json | 2 +- packages/ui/dist/contracts/textarea.json | 2 +- packages/ui/dist/contracts/time-picker.json | 2 +- packages/ui/dist/contracts/timeline.json | 2 +- packages/ui/dist/contracts/toast.json | 2 +- packages/ui/dist/contracts/toolbar.json | 2 +- packages/ui/dist/contracts/tooltip.json | 2 +- packages/ui/dist/contracts/tree.json | 2 +- packages/ui/dist/contracts/wizard.json | 2 +- .../ui/dist/copy/admin-form/manifest.json | 32 +- .../runtime/chunks/choice-DqwWT5pJ.js} | 9 +- .../runtime/chunks/element-DcrNU9Wh.js} | 5 +- .../runtime/chunks/forms-C3u5121t.js} | 5 +- .../runtime/chunks/native-D61761VL.js} | 5 +- .../runtime/components/admin-form.js | 9 +- .../admin-form/runtime/components/select.js | 9 +- .../runtime/components/text-field.js | 9 +- .../admin-form/runtime/components/textarea.js | 9 +- .../admin-form/runtime/register/admin-form.js | 5 +- .../admin-form/runtime/register/select.js | 5 +- .../admin-form/runtime/register/text-field.js | 5 +- .../admin-form/runtime/register/textarea.js | 5 +- packages/ui/dist/copy/alert/manifest.json | 16 +- ...{choice-B7mo5Eq3.js => choice-DqwWT5pJ.js} | 9 +- .../runtime/chunks/element-DcrNU9Wh.js} | 5 +- .../runtime/chunks/overlays-BW66WXLm.js} | 5 +- .../copy/alert/runtime/components/alert.js | 9 +- .../dist/copy/alert/runtime/register/alert.js | 5 +- packages/ui/dist/copy/avatar/manifest.json | 16 +- ...{choice-B7mo5Eq3.js => choice-DqwWT5pJ.js} | 9 +- .../runtime/chunks/display-l54fb8vw.js} | 5 +- .../runtime/chunks/element-DcrNU9Wh.js} | 5 +- .../copy/avatar/runtime/components/avatar.js | 9 +- .../copy/avatar/runtime/register/avatar.js | 5 +- packages/ui/dist/copy/badge/manifest.json | 16 +- .../badge/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../badge/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../badge/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../badge/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-D61761VL.js} | 5 +- .../copy/badge/runtime/components/badge.js | 9 +- .../dist/copy/badge/runtime/register/badge.js | 5 +- .../ui/dist/copy/breadcrumbs/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- ...ion-BfNzDYZB.js => navigation-CknoksQ5.js} | 5 +- .../runtime/components/breadcrumbs.js | 9 +- .../runtime/register/breadcrumbs.js | 5 +- .../ui/dist/copy/button-group/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-D61761VL.js} | 5 +- .../runtime/components/button-group.js | 9 +- .../runtime/register/button-group.js | 5 +- packages/ui/dist/copy/button/manifest.json | 16 +- .../button/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../button/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../button/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../button/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../button/runtime/chunks/native-BjBt1sUh.js | 289 ------ .../button/runtime/chunks/native-D61761VL.js | 288 ++++++ .../copy/button/runtime/components/button.js | 9 +- .../copy/button/runtime/register/button.js | 5 +- packages/ui/dist/copy/card/manifest.json | 16 +- .../card/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../card/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../card/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../card/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../card/runtime/chunks/native-BjBt1sUh.js | 289 ------ .../card/runtime/chunks/native-D61761VL.js | 288 ++++++ .../dist/copy/card/runtime/components/card.js | 9 +- .../dist/copy/card/runtime/register/card.js | 5 +- packages/ui/dist/copy/chart/manifest.json | 16 +- .../chart/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../chart/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/display-l54fb8vw.js} | 5 +- .../chart/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../chart/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../copy/chart/runtime/components/chart.js | 9 +- .../dist/copy/chart/runtime/register/chart.js | 5 +- packages/ui/dist/copy/checkbox/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../checkbox/runtime/components/checkbox.js | 9 +- .../checkbox/runtime/register/checkbox.js | 5 +- packages/ui/dist/copy/chip/manifest.json | 16 +- .../chip/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../chip/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../chip/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../chip/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/overlays-BW66WXLm.js} | 5 +- .../dist/copy/chip/runtime/components/chip.js | 9 +- .../dist/copy/chip/runtime/register/chip.js | 5 +- .../ui/dist/copy/code-editor/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/display-l54fb8vw.js} | 5 +- .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/components/code-editor.js | 9 +- .../runtime/register/code-editor.js | 5 +- packages/ui/dist/copy/combobox/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/navigation-CknoksQ5.js} | 5 +- .../combobox/runtime/components/combobox.js | 9 +- .../combobox/runtime/register/combobox.js | 5 +- .../dist/copy/command-palette/manifest.json | 20 +- ...anced-CqBF0dSb.js => advanced-BrFnVc0y.js} | 7 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/markup-AopKpwOF.js} | 3 +- .../runtime/components/command-palette.js | 9 +- .../runtime/register/command-palette.js | 5 +- .../dist/copy/compact-dashboard/manifest.json | 28 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/compositions-DWG4tv9E.js} | 7 +- .../runtime/chunks/display-Jm9bAsnb.js | 212 ---- .../runtime/chunks/display-l54fb8vw.js | 211 ++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/navigation-CknoksQ5.js} | 5 +- .../runtime/components/chart.js | 9 +- .../runtime/components/compact-dashboard.js | 9 +- .../runtime/register/chart.js | 5 +- .../runtime/register/compact-dashboard.js | 5 +- .../ui/dist/copy/data-table/manifest.json | 24 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/navigation-BfNzDYZB.js | 377 ------- .../runtime/chunks/navigation-CknoksQ5.js | 376 +++++++ .../runtime/chunks/tables-zo8ebTOo.js} | 5 +- .../runtime/components/data-table.js | 9 +- .../data-table/runtime/components/menu.js | 9 +- .../data-table/runtime/register/data-table.js | 5 +- .../copy/data-table/runtime/register/menu.js | 5 +- .../ui/dist/copy/date-picker/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../runtime/components/date-picker.js | 9 +- .../runtime/register/date-picker.js | 5 +- .../dist/copy/description-list/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../runtime/components/description-list.js | 9 +- .../runtime/register/description-list.js | 5 +- .../ui/dist/copy/diagnostics/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/display-Jm9bAsnb.js | 212 ---- .../runtime/chunks/display-l54fb8vw.js | 211 ++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/components/diagnostics.js | 9 +- .../runtime/register/diagnostics.js | 5 +- packages/ui/dist/copy/dialog/manifest.json | 16 +- .../dialog/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../dialog/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../dialog/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../dialog/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/overlays-BW66WXLm.js} | 5 +- .../copy/dialog/runtime/components/dialog.js | 9 +- .../copy/dialog/runtime/register/dialog.js | 5 +- packages/ui/dist/copy/diff-view/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/display-Jm9bAsnb.js | 212 ---- .../runtime/chunks/display-l54fb8vw.js | 211 ++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../diff-view/runtime/components/diff-view.js | 9 +- .../diff-view/runtime/register/diff-view.js | 5 +- .../ui/dist/copy/disclosure/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/navigation-BfNzDYZB.js | 377 ------- .../runtime/chunks/navigation-CknoksQ5.js | 376 +++++++ .../runtime/components/disclosure.js | 9 +- .../disclosure/runtime/register/disclosure.js | 5 +- packages/ui/dist/copy/drawer/manifest.json | 16 +- .../drawer/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../drawer/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../drawer/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../drawer/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/overlays-BW66WXLm.js | 244 +++++ .../runtime/chunks/overlays-BwgpF4jI.js | 245 ----- .../copy/drawer/runtime/components/drawer.js | 9 +- .../copy/drawer/runtime/register/drawer.js | 5 +- .../ui/dist/copy/editor-search/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/display-Jm9bAsnb.js | 212 ---- .../runtime/chunks/display-l54fb8vw.js | 211 ++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/components/editor-search.js | 9 +- .../runtime/register/editor-search.js | 5 +- .../ui/dist/copy/empty-state/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/overlays-BW66WXLm.js | 244 +++++ .../runtime/chunks/overlays-BwgpF4jI.js | 245 ----- .../runtime/components/empty-state.js | 9 +- .../runtime/register/empty-state.js | 5 +- .../ui/dist/copy/error-state/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/overlays-BW66WXLm.js | 244 +++++ .../runtime/chunks/overlays-BwgpF4jI.js | 245 ----- .../runtime/components/error-state.js | 9 +- .../runtime/register/error-state.js | 5 +- packages/ui/dist/copy/field/manifest.json | 16 +- .../field/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../field/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../field/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../field/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../field/runtime/chunks/native-BjBt1sUh.js | 289 ------ .../field/runtime/chunks/native-D61761VL.js | 288 ++++++ .../copy/field/runtime/components/field.js | 9 +- .../dist/copy/field/runtime/register/field.js | 5 +- packages/ui/dist/copy/fieldset/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../fieldset/runtime/components/fieldset.js | 9 +- .../fieldset/runtime/register/fieldset.js | 5 +- .../ui/dist/copy/file-browser/manifest.json | 32 +- ...anced-CqBF0dSb.js => advanced-BrFnVc0y.js} | 7 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/compositions-DWG4tv9E.js} | 7 +- .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- ...{markup-DeQ4bEMR.js => markup-AopKpwOF.js} | 3 +- .../runtime/chunks/navigation-BfNzDYZB.js | 377 ------- .../runtime/chunks/navigation-CknoksQ5.js | 376 +++++++ .../runtime/components/file-browser.js | 9 +- .../file-browser/runtime/components/tree.js | 9 +- .../runtime/register/file-browser.js | 5 +- .../file-browser/runtime/register/tree.js | 5 +- .../ui/dist/copy/file-input/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../runtime/components/file-input.js | 9 +- .../file-input/runtime/register/file-input.js | 5 +- .../dist/copy/filterable-table/manifest.json | 24 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../runtime/chunks/tables-zo8ebTOo.js} | 5 +- .../runtime/components/filterable-table.js | 9 +- .../runtime/components/search-field.js | 9 +- .../runtime/register/filterable-table.js | 5 +- .../runtime/register/search-field.js | 5 +- .../ui/dist/copy/form-builder/manifest.json | 26 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- ...r-BvWZCBPR.js => form-builder-CkeTBQe-.js} | 12 +- .../runtime/chunks/form-builder-DbZUZMo1.js} | 8 +- ...-BKRLylvq.js => form-workflow-B183Y5gc.js} | 424 ++++---- .../runtime/chunks/markup-AopKpwOF.js} | 3 +- .../runtime/register/form-builder.js | 7 +- .../dist/copy/i3-window-frame/manifest.json | 20 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ ...s-D57dCsBz.js => compositions-DWG4tv9E.js} | 7 +- .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/navigation-BfNzDYZB.js | 377 ------- .../runtime/chunks/navigation-CknoksQ5.js | 376 +++++++ .../runtime/components/i3-window-frame.js | 9 +- .../runtime/register/i3-window-frame.js | 5 +- .../ui/dist/copy/icon-button/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../runtime/components/icon-button.js | 9 +- .../runtime/register/icon-button.js | 5 +- packages/ui/dist/copy/kbd/manifest.json | 16 +- .../kbd/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../kbd/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../kbd/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../kbd/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../kbd/runtime/chunks/native-BjBt1sUh.js | 289 ------ .../kbd/runtime/chunks/native-D61761VL.js | 288 ++++++ .../dist/copy/kbd/runtime/components/kbd.js | 9 +- .../ui/dist/copy/kbd/runtime/register/kbd.js | 5 +- packages/ui/dist/copy/link/manifest.json | 16 +- .../link/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../link/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../link/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../link/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../link/runtime/chunks/native-BjBt1sUh.js | 289 ------ .../link/runtime/chunks/native-D61761VL.js | 288 ++++++ .../dist/copy/link/runtime/components/link.js | 9 +- .../dist/copy/link/runtime/register/link.js | 5 +- packages/ui/dist/copy/list/manifest.json | 16 +- .../list/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../list/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../list/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../list/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../list/runtime/chunks/native-BjBt1sUh.js | 289 ------ .../list/runtime/chunks/native-D61761VL.js | 288 ++++++ .../dist/copy/list/runtime/components/list.js | 9 +- .../dist/copy/list/runtime/register/list.js | 5 +- .../dist/copy/loading-indicator/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../runtime/components/loading-indicator.js | 9 +- .../runtime/register/loading-indicator.js | 5 +- packages/ui/dist/copy/menu/manifest.json | 16 +- .../menu/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../menu/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../menu/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../menu/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/navigation-BfNzDYZB.js | 377 ------- .../runtime/chunks/navigation-CknoksQ5.js | 376 +++++++ .../dist/copy/menu/runtime/components/menu.js | 9 +- .../dist/copy/menu/runtime/register/menu.js | 5 +- .../ui/dist/copy/multiselect/manifest.json | 20 +- ...anced-CqBF0dSb.js => advanced-BrFnVc0y.js} | 7 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/markup-AopKpwOF.js | 53 + .../runtime/chunks/markup-DeQ4bEMR.js | 54 - .../runtime/components/multiselect.js | 9 +- .../runtime/register/multiselect.js | 5 +- .../ui/dist/copy/number-field/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../runtime/components/number-field.js | 9 +- .../runtime/register/number-field.js | 5 +- .../ui/dist/copy/pagination/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/tables-zo8ebTOo.js} | 5 +- .../runtime/components/pagination.js | 9 +- .../pagination/runtime/register/pagination.js | 5 +- packages/ui/dist/copy/popover/manifest.json | 16 +- .../popover/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../popover/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/overlays-BW66WXLm.js | 244 +++++ .../runtime/chunks/overlays-BwgpF4jI.js | 245 ----- .../popover/runtime/components/popover.js | 9 +- .../copy/popover/runtime/register/popover.js | 5 +- packages/ui/dist/copy/progress/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../progress/runtime/components/progress.js | 9 +- .../progress/runtime/register/progress.js | 5 +- .../ui/dist/copy/radio-group/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../runtime/components/radio-group.js | 9 +- .../runtime/register/radio-group.js | 5 +- packages/ui/dist/copy/range/manifest.json | 16 +- .../range/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../range/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../range/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../range/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../range/runtime/chunks/native-BjBt1sUh.js | 289 ------ .../range/runtime/chunks/native-D61761VL.js | 288 ++++++ .../copy/range/runtime/components/range.js | 9 +- .../dist/copy/range/runtime/register/range.js | 5 +- packages/ui/dist/copy/repeater/manifest.json | 20 +- .../runtime/chunks/advanced-BrFnVc0y.js | 344 +++++++ .../runtime/chunks/advanced-CqBF0dSb.js | 345 ------- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/markup-AopKpwOF.js | 53 + .../runtime/chunks/markup-DeQ4bEMR.js | 54 - .../repeater/runtime/components/repeater.js | 9 +- .../repeater/runtime/register/repeater.js | 5 +- .../ui/dist/copy/search-field/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../runtime/components/search-field.js | 9 +- .../runtime/register/search-field.js | 5 +- .../dist/copy/segmented-control/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../runtime/components/segmented-control.js | 9 +- .../runtime/register/segmented-control.js | 5 +- packages/ui/dist/copy/select/manifest.json | 16 +- .../select/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../select/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../select/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../select/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../select/runtime/chunks/native-BjBt1sUh.js | 289 ------ .../select/runtime/chunks/native-D61761VL.js | 288 ++++++ .../copy/select/runtime/components/select.js | 9 +- .../copy/select/runtime/register/select.js | 5 +- .../ui/dist/copy/settings-panel/manifest.json | 24 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/forms-C3u5121t.js} | 5 +- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../runtime/components/settings-panel.js | 9 +- .../runtime/components/switch.js | 9 +- .../runtime/register/settings-panel.js | 5 +- .../settings-panel/runtime/register/switch.js | 5 +- .../ui/dist/copy/sidebar-nav/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/navigation-BfNzDYZB.js | 377 ------- .../runtime/chunks/navigation-CknoksQ5.js | 376 +++++++ .../runtime/components/sidebar-nav.js | 9 +- .../runtime/register/sidebar-nav.js | 5 +- packages/ui/dist/copy/skeleton/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../skeleton/runtime/components/skeleton.js | 9 +- .../skeleton/runtime/register/skeleton.js | 5 +- packages/ui/dist/copy/skip-link/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../skip-link/runtime/components/skip-link.js | 9 +- .../skip-link/runtime/register/skip-link.js | 5 +- packages/ui/dist/copy/switch/manifest.json | 16 +- .../switch/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../switch/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../switch/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../switch/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../switch/runtime/chunks/native-BjBt1sUh.js | 289 ------ .../switch/runtime/chunks/native-D61761VL.js | 288 ++++++ .../copy/switch/runtime/components/switch.js | 9 +- .../copy/switch/runtime/register/switch.js | 5 +- packages/ui/dist/copy/table/manifest.json | 16 +- .../table/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../table/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../table/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../table/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../table/runtime/chunks/tables-Cjr1EIJz.js | 217 ---- .../table/runtime/chunks/tables-zo8ebTOo.js | 216 ++++ .../copy/table/runtime/components/table.js | 9 +- .../dist/copy/table/runtime/register/table.js | 5 +- packages/ui/dist/copy/tabs/manifest.json | 16 +- .../tabs/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../tabs/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../tabs/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../tabs/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/navigation-BfNzDYZB.js | 377 ------- .../runtime/chunks/navigation-CknoksQ5.js | 376 +++++++ .../dist/copy/tabs/runtime/components/tabs.js | 9 +- .../dist/copy/tabs/runtime/register/tabs.js | 5 +- packages/ui/dist/copy/terminal/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/display-Jm9bAsnb.js | 212 ---- .../runtime/chunks/display-l54fb8vw.js | 211 ++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../terminal/runtime/components/terminal.js | 9 +- .../terminal/runtime/register/terminal.js | 5 +- .../ui/dist/copy/text-field/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../runtime/components/text-field.js | 9 +- .../text-field/runtime/register/text-field.js | 5 +- packages/ui/dist/copy/textarea/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../textarea/runtime/components/textarea.js | 9 +- .../textarea/runtime/register/textarea.js | 5 +- .../ui/dist/copy/time-picker/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../runtime/components/time-picker.js | 9 +- .../runtime/register/time-picker.js | 5 +- packages/ui/dist/copy/timeline/manifest.json | 16 +- .../runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/native-BjBt1sUh.js | 289 ------ .../runtime/chunks/native-D61761VL.js | 288 ++++++ .../timeline/runtime/components/timeline.js | 9 +- .../timeline/runtime/register/timeline.js | 5 +- packages/ui/dist/copy/toast/manifest.json | 16 +- .../toast/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../toast/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../toast/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../toast/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../toast/runtime/chunks/overlays-BW66WXLm.js | 244 +++++ .../toast/runtime/chunks/overlays-BwgpF4jI.js | 245 ----- .../copy/toast/runtime/components/toast.js | 9 +- .../dist/copy/toast/runtime/register/toast.js | 5 +- packages/ui/dist/copy/toolbar/manifest.json | 20 +- .../toolbar/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../toolbar/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/navigation-BfNzDYZB.js | 377 ------- .../runtime/chunks/navigation-CknoksQ5.js | 376 +++++++ .../copy/toolbar/runtime/components/menu.js | 9 +- .../toolbar/runtime/components/toolbar.js | 9 +- .../copy/toolbar/runtime/register/menu.js | 5 +- .../copy/toolbar/runtime/register/toolbar.js | 5 +- packages/ui/dist/copy/tooltip/manifest.json | 16 +- .../tooltip/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../tooltip/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../runtime/chunks/overlays-BW66WXLm.js | 244 +++++ .../runtime/chunks/overlays-BwgpF4jI.js | 245 ----- .../tooltip/runtime/components/tooltip.js | 9 +- .../copy/tooltip/runtime/register/tooltip.js | 5 +- packages/ui/dist/copy/tree/manifest.json | 20 +- .../tree/runtime/chunks/advanced-BrFnVc0y.js | 344 +++++++ .../tree/runtime/chunks/advanced-CqBF0dSb.js | 345 ------- .../tree/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../tree/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../tree/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../tree/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../tree/runtime/chunks/markup-AopKpwOF.js | 53 + .../tree/runtime/chunks/markup-DeQ4bEMR.js | 54 - .../dist/copy/tree/runtime/components/tree.js | 9 +- .../dist/copy/tree/runtime/register/tree.js | 5 +- packages/ui/dist/copy/wizard/manifest.json | 16 +- .../wizard/runtime/chunks/choice-B7mo5Eq3.js | 938 ------------------ .../wizard/runtime/chunks/choice-DqwWT5pJ.js | 935 +++++++++++++++++ .../wizard/runtime/chunks/element-DcrNU9Wh.js | 231 +++++ .../wizard/runtime/chunks/element-Dovcr9Ky.js | 232 ----- .../{forms-CE_hP1hg.js => forms-C3u5121t.js} | 5 +- .../copy/wizard/runtime/components/wizard.js | 9 +- .../copy/wizard/runtime/register/wizard.js | 5 +- packages/ui/dist/enhance/choice.js | 2 +- packages/ui/dist/enhance/form-builder.js | 2 +- packages/ui/dist/enhance/form-workflow.js | 2 +- packages/ui/dist/index.js | 2 +- packages/ui/dist/manifest.json | 872 ++++++++-------- packages/ui/dist/register/admin-form.js | 5 +- packages/ui/dist/register/alert.js | 5 +- packages/ui/dist/register/avatar.js | 5 +- packages/ui/dist/register/badge.js | 5 +- packages/ui/dist/register/breadcrumbs.js | 5 +- packages/ui/dist/register/button-group.js | 5 +- packages/ui/dist/register/button.js | 5 +- packages/ui/dist/register/card.js | 5 +- packages/ui/dist/register/chart.js | 5 +- packages/ui/dist/register/checkbox.js | 5 +- packages/ui/dist/register/chip.js | 5 +- packages/ui/dist/register/code-editor.js | 5 +- packages/ui/dist/register/combobox.js | 5 +- packages/ui/dist/register/command-palette.js | 5 +- .../ui/dist/register/compact-dashboard.js | 5 +- packages/ui/dist/register/data-table.js | 5 +- packages/ui/dist/register/date-picker.js | 5 +- packages/ui/dist/register/description-list.js | 5 +- packages/ui/dist/register/diagnostics.js | 5 +- packages/ui/dist/register/dialog.js | 5 +- packages/ui/dist/register/diff-view.js | 5 +- packages/ui/dist/register/disclosure.js | 5 +- packages/ui/dist/register/drawer.js | 5 +- packages/ui/dist/register/editor-search.js | 5 +- packages/ui/dist/register/empty-state.js | 5 +- packages/ui/dist/register/error-state.js | 5 +- packages/ui/dist/register/field.js | 5 +- packages/ui/dist/register/fieldset.js | 5 +- packages/ui/dist/register/file-browser.js | 5 +- packages/ui/dist/register/file-input.js | 5 +- packages/ui/dist/register/filterable-table.js | 5 +- packages/ui/dist/register/form-builder.js | 7 +- packages/ui/dist/register/i3-window-frame.js | 5 +- packages/ui/dist/register/icon-button.js | 5 +- packages/ui/dist/register/kbd.js | 5 +- packages/ui/dist/register/link.js | 5 +- packages/ui/dist/register/list.js | 5 +- .../ui/dist/register/loading-indicator.js | 5 +- packages/ui/dist/register/menu.js | 5 +- packages/ui/dist/register/multiselect.js | 5 +- packages/ui/dist/register/number-field.js | 5 +- packages/ui/dist/register/pagination.js | 5 +- packages/ui/dist/register/popover.js | 5 +- packages/ui/dist/register/progress.js | 5 +- packages/ui/dist/register/radio-group.js | 5 +- packages/ui/dist/register/range.js | 5 +- packages/ui/dist/register/repeater.js | 5 +- packages/ui/dist/register/search-field.js | 5 +- .../ui/dist/register/segmented-control.js | 5 +- packages/ui/dist/register/select.js | 5 +- packages/ui/dist/register/settings-panel.js | 5 +- packages/ui/dist/register/sidebar-nav.js | 5 +- packages/ui/dist/register/skeleton.js | 5 +- packages/ui/dist/register/skip-link.js | 5 +- packages/ui/dist/register/switch.js | 5 +- packages/ui/dist/register/table.js | 5 +- packages/ui/dist/register/tabs.js | 5 +- packages/ui/dist/register/terminal.js | 5 +- packages/ui/dist/register/text-field.js | 5 +- packages/ui/dist/register/textarea.js | 5 +- packages/ui/dist/register/time-picker.js | 5 +- packages/ui/dist/register/timeline.js | 5 +- packages/ui/dist/register/toast.js | 5 +- packages/ui/dist/register/toolbar.js | 5 +- packages/ui/dist/register/tooltip.js | 5 +- packages/ui/dist/register/tree.js | 5 +- packages/ui/dist/register/wizard.js | 5 +- site/src/layouts/SiteLayout.astro | 4 +- tests/browser/portal.spec.js | 2 + 842 files changed, 92437 insertions(+), 92781 deletions(-) rename packages/ui/dist/chunks/{advanced-CqBF0dSb.js => advanced-BrFnVc0y.js} (98%) rename packages/ui/dist/{copy/admin-form/runtime/chunks/choice-B7mo5Eq3.js => chunks/choice-DqwWT5pJ.js} (99%) rename packages/ui/dist/{copy/compact-dashboard/runtime/chunks/compositions-D57dCsBz.js => chunks/compositions-DWG4tv9E.js} (91%) rename packages/ui/dist/{copy/chart/runtime/chunks/display-Jm9bAsnb.js => chunks/display-l54fb8vw.js} (98%) rename packages/ui/dist/{copy/alert/runtime/chunks/element-Dovcr9Ky.js => chunks/element-DcrNU9Wh.js} (98%) rename packages/ui/dist/chunks/{form-builder-BvWZCBPR.js => form-builder-CkeTBQe-.js} (82%) rename packages/ui/dist/{copy/form-builder/runtime/chunks/form-builder-BRIaVVFY.js => chunks/form-builder-DbZUZMo1.js} (99%) rename packages/ui/dist/chunks/{form-workflow-BKRLylvq.js => form-workflow-B183Y5gc.js} (99%) rename packages/ui/dist/{copy/settings-panel/runtime/chunks/forms-CE_hP1hg.js => chunks/forms-C3u5121t.js} (96%) rename packages/ui/dist/{copy/form-builder/runtime/chunks/markup-DeQ4bEMR.js => chunks/markup-AopKpwOF.js} (97%) rename packages/ui/dist/{copy/badge/runtime/chunks/native-BjBt1sUh.js => chunks/native-D61761VL.js} (98%) rename packages/ui/dist/{copy/compact-dashboard/runtime/chunks/navigation-BfNzDYZB.js => chunks/navigation-CknoksQ5.js} (99%) rename packages/ui/dist/{copy/chip/runtime/chunks/overlays-BwgpF4jI.js => chunks/overlays-BW66WXLm.js} (98%) rename packages/ui/dist/{copy/data-table/runtime/chunks/tables-Cjr1EIJz.js => chunks/tables-zo8ebTOo.js} (98%) rename packages/ui/dist/{chunks/choice-B7mo5Eq3.js => copy/admin-form/runtime/chunks/choice-DqwWT5pJ.js} (99%) rename packages/ui/dist/{chunks/element-Dovcr9Ky.js => copy/admin-form/runtime/chunks/element-DcrNU9Wh.js} (98%) rename packages/ui/dist/{chunks/forms-CE_hP1hg.js => copy/admin-form/runtime/chunks/forms-C3u5121t.js} (96%) rename packages/ui/dist/{chunks/native-BjBt1sUh.js => copy/admin-form/runtime/chunks/native-D61761VL.js} (98%) rename packages/ui/dist/copy/alert/runtime/chunks/{choice-B7mo5Eq3.js => choice-DqwWT5pJ.js} (99%) rename packages/ui/dist/copy/{avatar/runtime/chunks/element-Dovcr9Ky.js => alert/runtime/chunks/element-DcrNU9Wh.js} (98%) rename packages/ui/dist/copy/{dialog/runtime/chunks/overlays-BwgpF4jI.js => alert/runtime/chunks/overlays-BW66WXLm.js} (98%) rename packages/ui/dist/copy/avatar/runtime/chunks/{choice-B7mo5Eq3.js => choice-DqwWT5pJ.js} (99%) rename packages/ui/dist/copy/{code-editor/runtime/chunks/display-Jm9bAsnb.js => avatar/runtime/chunks/display-l54fb8vw.js} (98%) rename packages/ui/dist/copy/{admin-form/runtime/chunks/element-Dovcr9Ky.js => avatar/runtime/chunks/element-DcrNU9Wh.js} (98%) delete mode 100644 packages/ui/dist/copy/badge/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/badge/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/badge/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/badge/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/copy/{button-group/runtime/chunks/native-BjBt1sUh.js => badge/runtime/chunks/native-D61761VL.js} (98%) delete mode 100644 packages/ui/dist/copy/breadcrumbs/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/breadcrumbs/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/breadcrumbs/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/breadcrumbs/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/copy/breadcrumbs/runtime/chunks/{navigation-BfNzDYZB.js => navigation-CknoksQ5.js} (99%) delete mode 100644 packages/ui/dist/copy/button-group/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/button-group/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/button-group/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/button-group/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/copy/{admin-form/runtime/chunks/native-BjBt1sUh.js => button-group/runtime/chunks/native-D61761VL.js} (98%) delete mode 100644 packages/ui/dist/copy/button/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/button/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/button/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/button/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/button/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/button/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/card/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/card/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/card/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/card/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/card/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/card/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/chart/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/chart/runtime/chunks/choice-DqwWT5pJ.js rename packages/ui/dist/copy/{avatar/runtime/chunks/display-Jm9bAsnb.js => chart/runtime/chunks/display-l54fb8vw.js} (98%) create mode 100644 packages/ui/dist/copy/chart/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/chart/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/checkbox/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/checkbox/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/checkbox/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/checkbox/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/checkbox/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/checkbox/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/chip/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/chip/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/chip/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/chip/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/copy/{alert/runtime/chunks/overlays-BwgpF4jI.js => chip/runtime/chunks/overlays-BW66WXLm.js} (98%) delete mode 100644 packages/ui/dist/copy/code-editor/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/code-editor/runtime/chunks/choice-DqwWT5pJ.js rename packages/ui/dist/{chunks/display-Jm9bAsnb.js => copy/code-editor/runtime/chunks/display-l54fb8vw.js} (98%) create mode 100644 packages/ui/dist/copy/code-editor/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/code-editor/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/combobox/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/combobox/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/combobox/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/combobox/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/{chunks/navigation-BfNzDYZB.js => copy/combobox/runtime/chunks/navigation-CknoksQ5.js} (99%) rename packages/ui/dist/copy/command-palette/runtime/chunks/{advanced-CqBF0dSb.js => advanced-BrFnVc0y.js} (98%) delete mode 100644 packages/ui/dist/copy/command-palette/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/command-palette/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/command-palette/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/command-palette/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/{chunks/markup-DeQ4bEMR.js => copy/command-palette/runtime/chunks/markup-AopKpwOF.js} (97%) delete mode 100644 packages/ui/dist/copy/compact-dashboard/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/compact-dashboard/runtime/chunks/choice-DqwWT5pJ.js rename packages/ui/dist/copy/{file-browser/runtime/chunks/compositions-D57dCsBz.js => compact-dashboard/runtime/chunks/compositions-DWG4tv9E.js} (91%) delete mode 100644 packages/ui/dist/copy/compact-dashboard/runtime/chunks/display-Jm9bAsnb.js create mode 100644 packages/ui/dist/copy/compact-dashboard/runtime/chunks/display-l54fb8vw.js create mode 100644 packages/ui/dist/copy/compact-dashboard/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/compact-dashboard/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/copy/{combobox/runtime/chunks/navigation-BfNzDYZB.js => compact-dashboard/runtime/chunks/navigation-CknoksQ5.js} (99%) delete mode 100644 packages/ui/dist/copy/data-table/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/data-table/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/data-table/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/data-table/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/data-table/runtime/chunks/navigation-BfNzDYZB.js create mode 100644 packages/ui/dist/copy/data-table/runtime/chunks/navigation-CknoksQ5.js rename packages/ui/dist/copy/{filterable-table/runtime/chunks/tables-Cjr1EIJz.js => data-table/runtime/chunks/tables-zo8ebTOo.js} (98%) delete mode 100644 packages/ui/dist/copy/date-picker/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/date-picker/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/date-picker/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/date-picker/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/date-picker/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/date-picker/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/description-list/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/description-list/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/description-list/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/description-list/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/description-list/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/description-list/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/diagnostics/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/diagnostics/runtime/chunks/choice-DqwWT5pJ.js delete mode 100644 packages/ui/dist/copy/diagnostics/runtime/chunks/display-Jm9bAsnb.js create mode 100644 packages/ui/dist/copy/diagnostics/runtime/chunks/display-l54fb8vw.js create mode 100644 packages/ui/dist/copy/diagnostics/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/diagnostics/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/dialog/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/dialog/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/dialog/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/dialog/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/{chunks/overlays-BwgpF4jI.js => copy/dialog/runtime/chunks/overlays-BW66WXLm.js} (98%) delete mode 100644 packages/ui/dist/copy/diff-view/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/diff-view/runtime/chunks/choice-DqwWT5pJ.js delete mode 100644 packages/ui/dist/copy/diff-view/runtime/chunks/display-Jm9bAsnb.js create mode 100644 packages/ui/dist/copy/diff-view/runtime/chunks/display-l54fb8vw.js create mode 100644 packages/ui/dist/copy/diff-view/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/diff-view/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/disclosure/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/disclosure/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/disclosure/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/disclosure/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/disclosure/runtime/chunks/navigation-BfNzDYZB.js create mode 100644 packages/ui/dist/copy/disclosure/runtime/chunks/navigation-CknoksQ5.js delete mode 100644 packages/ui/dist/copy/drawer/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/drawer/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/drawer/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/drawer/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/drawer/runtime/chunks/overlays-BW66WXLm.js delete mode 100644 packages/ui/dist/copy/drawer/runtime/chunks/overlays-BwgpF4jI.js delete mode 100644 packages/ui/dist/copy/editor-search/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/editor-search/runtime/chunks/choice-DqwWT5pJ.js delete mode 100644 packages/ui/dist/copy/editor-search/runtime/chunks/display-Jm9bAsnb.js create mode 100644 packages/ui/dist/copy/editor-search/runtime/chunks/display-l54fb8vw.js create mode 100644 packages/ui/dist/copy/editor-search/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/editor-search/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/empty-state/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/empty-state/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/empty-state/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/empty-state/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/empty-state/runtime/chunks/overlays-BW66WXLm.js delete mode 100644 packages/ui/dist/copy/empty-state/runtime/chunks/overlays-BwgpF4jI.js delete mode 100644 packages/ui/dist/copy/error-state/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/error-state/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/error-state/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/error-state/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/error-state/runtime/chunks/overlays-BW66WXLm.js delete mode 100644 packages/ui/dist/copy/error-state/runtime/chunks/overlays-BwgpF4jI.js delete mode 100644 packages/ui/dist/copy/field/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/field/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/field/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/field/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/field/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/field/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/fieldset/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/fieldset/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/fieldset/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/fieldset/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/fieldset/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/fieldset/runtime/chunks/native-D61761VL.js rename packages/ui/dist/copy/file-browser/runtime/chunks/{advanced-CqBF0dSb.js => advanced-BrFnVc0y.js} (98%) delete mode 100644 packages/ui/dist/copy/file-browser/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/file-browser/runtime/chunks/choice-DqwWT5pJ.js rename packages/ui/dist/{chunks/compositions-D57dCsBz.js => copy/file-browser/runtime/chunks/compositions-DWG4tv9E.js} (91%) create mode 100644 packages/ui/dist/copy/file-browser/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/file-browser/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/copy/file-browser/runtime/chunks/{markup-DeQ4bEMR.js => markup-AopKpwOF.js} (97%) delete mode 100644 packages/ui/dist/copy/file-browser/runtime/chunks/navigation-BfNzDYZB.js create mode 100644 packages/ui/dist/copy/file-browser/runtime/chunks/navigation-CknoksQ5.js delete mode 100644 packages/ui/dist/copy/file-input/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/file-input/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/file-input/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/file-input/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/file-input/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/file-input/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/filterable-table/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/filterable-table/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/filterable-table/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/filterable-table/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/filterable-table/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/filterable-table/runtime/chunks/native-D61761VL.js rename packages/ui/dist/copy/{pagination/runtime/chunks/tables-Cjr1EIJz.js => filterable-table/runtime/chunks/tables-zo8ebTOo.js} (98%) delete mode 100644 packages/ui/dist/copy/form-builder/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/form-builder/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/form-builder/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/form-builder/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/copy/form-builder/runtime/chunks/{form-builder-BvWZCBPR.js => form-builder-CkeTBQe-.js} (82%) rename packages/ui/dist/{chunks/form-builder-BRIaVVFY.js => copy/form-builder/runtime/chunks/form-builder-DbZUZMo1.js} (99%) rename packages/ui/dist/copy/form-builder/runtime/chunks/{form-workflow-BKRLylvq.js => form-workflow-B183Y5gc.js} (99%) rename packages/ui/dist/copy/{command-palette/runtime/chunks/markup-DeQ4bEMR.js => form-builder/runtime/chunks/markup-AopKpwOF.js} (97%) delete mode 100644 packages/ui/dist/copy/i3-window-frame/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/i3-window-frame/runtime/chunks/choice-DqwWT5pJ.js rename packages/ui/dist/copy/i3-window-frame/runtime/chunks/{compositions-D57dCsBz.js => compositions-DWG4tv9E.js} (91%) create mode 100644 packages/ui/dist/copy/i3-window-frame/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/i3-window-frame/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/i3-window-frame/runtime/chunks/navigation-BfNzDYZB.js create mode 100644 packages/ui/dist/copy/i3-window-frame/runtime/chunks/navigation-CknoksQ5.js delete mode 100644 packages/ui/dist/copy/icon-button/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/icon-button/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/icon-button/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/icon-button/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/icon-button/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/icon-button/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/kbd/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/kbd/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/kbd/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/kbd/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/kbd/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/kbd/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/link/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/link/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/link/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/link/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/link/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/link/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/list/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/list/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/list/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/list/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/list/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/list/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/loading-indicator/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/loading-indicator/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/loading-indicator/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/loading-indicator/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/loading-indicator/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/loading-indicator/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/menu/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/menu/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/menu/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/menu/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/menu/runtime/chunks/navigation-BfNzDYZB.js create mode 100644 packages/ui/dist/copy/menu/runtime/chunks/navigation-CknoksQ5.js rename packages/ui/dist/copy/multiselect/runtime/chunks/{advanced-CqBF0dSb.js => advanced-BrFnVc0y.js} (98%) delete mode 100644 packages/ui/dist/copy/multiselect/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/multiselect/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/multiselect/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/multiselect/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/multiselect/runtime/chunks/markup-AopKpwOF.js delete mode 100644 packages/ui/dist/copy/multiselect/runtime/chunks/markup-DeQ4bEMR.js delete mode 100644 packages/ui/dist/copy/number-field/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/number-field/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/number-field/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/number-field/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/number-field/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/number-field/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/pagination/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/pagination/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/pagination/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/pagination/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/{chunks/tables-Cjr1EIJz.js => copy/pagination/runtime/chunks/tables-zo8ebTOo.js} (98%) delete mode 100644 packages/ui/dist/copy/popover/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/popover/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/popover/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/popover/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/popover/runtime/chunks/overlays-BW66WXLm.js delete mode 100644 packages/ui/dist/copy/popover/runtime/chunks/overlays-BwgpF4jI.js delete mode 100644 packages/ui/dist/copy/progress/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/progress/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/progress/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/progress/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/progress/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/progress/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/radio-group/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/radio-group/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/radio-group/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/radio-group/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/radio-group/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/radio-group/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/range/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/range/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/range/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/range/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/range/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/range/runtime/chunks/native-D61761VL.js create mode 100644 packages/ui/dist/copy/repeater/runtime/chunks/advanced-BrFnVc0y.js delete mode 100644 packages/ui/dist/copy/repeater/runtime/chunks/advanced-CqBF0dSb.js delete mode 100644 packages/ui/dist/copy/repeater/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/repeater/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/repeater/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/repeater/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/repeater/runtime/chunks/markup-AopKpwOF.js delete mode 100644 packages/ui/dist/copy/repeater/runtime/chunks/markup-DeQ4bEMR.js delete mode 100644 packages/ui/dist/copy/search-field/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/search-field/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/search-field/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/search-field/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/search-field/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/search-field/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/segmented-control/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/segmented-control/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/segmented-control/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/segmented-control/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/segmented-control/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/segmented-control/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/select/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/select/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/select/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/select/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/select/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/select/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/settings-panel/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/settings-panel/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/settings-panel/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/settings-panel/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/copy/{admin-form/runtime/chunks/forms-CE_hP1hg.js => settings-panel/runtime/chunks/forms-C3u5121t.js} (96%) delete mode 100644 packages/ui/dist/copy/settings-panel/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/settings-panel/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/sidebar-nav/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/sidebar-nav/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/sidebar-nav/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/sidebar-nav/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/sidebar-nav/runtime/chunks/navigation-BfNzDYZB.js create mode 100644 packages/ui/dist/copy/sidebar-nav/runtime/chunks/navigation-CknoksQ5.js delete mode 100644 packages/ui/dist/copy/skeleton/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/skeleton/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/skeleton/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/skeleton/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/skeleton/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/skeleton/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/skip-link/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/skip-link/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/skip-link/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/skip-link/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/skip-link/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/skip-link/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/switch/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/switch/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/switch/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/switch/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/switch/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/switch/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/table/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/table/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/table/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/table/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/table/runtime/chunks/tables-Cjr1EIJz.js create mode 100644 packages/ui/dist/copy/table/runtime/chunks/tables-zo8ebTOo.js delete mode 100644 packages/ui/dist/copy/tabs/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/tabs/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/tabs/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/tabs/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/tabs/runtime/chunks/navigation-BfNzDYZB.js create mode 100644 packages/ui/dist/copy/tabs/runtime/chunks/navigation-CknoksQ5.js delete mode 100644 packages/ui/dist/copy/terminal/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/terminal/runtime/chunks/choice-DqwWT5pJ.js delete mode 100644 packages/ui/dist/copy/terminal/runtime/chunks/display-Jm9bAsnb.js create mode 100644 packages/ui/dist/copy/terminal/runtime/chunks/display-l54fb8vw.js create mode 100644 packages/ui/dist/copy/terminal/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/terminal/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/text-field/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/text-field/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/text-field/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/text-field/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/text-field/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/text-field/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/textarea/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/textarea/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/textarea/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/textarea/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/textarea/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/textarea/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/time-picker/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/time-picker/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/time-picker/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/time-picker/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/time-picker/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/time-picker/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/timeline/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/timeline/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/timeline/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/timeline/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/timeline/runtime/chunks/native-BjBt1sUh.js create mode 100644 packages/ui/dist/copy/timeline/runtime/chunks/native-D61761VL.js delete mode 100644 packages/ui/dist/copy/toast/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/toast/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/toast/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/toast/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/toast/runtime/chunks/overlays-BW66WXLm.js delete mode 100644 packages/ui/dist/copy/toast/runtime/chunks/overlays-BwgpF4jI.js delete mode 100644 packages/ui/dist/copy/toolbar/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/toolbar/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/toolbar/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/toolbar/runtime/chunks/element-Dovcr9Ky.js delete mode 100644 packages/ui/dist/copy/toolbar/runtime/chunks/navigation-BfNzDYZB.js create mode 100644 packages/ui/dist/copy/toolbar/runtime/chunks/navigation-CknoksQ5.js delete mode 100644 packages/ui/dist/copy/tooltip/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/tooltip/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/tooltip/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/tooltip/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/tooltip/runtime/chunks/overlays-BW66WXLm.js delete mode 100644 packages/ui/dist/copy/tooltip/runtime/chunks/overlays-BwgpF4jI.js create mode 100644 packages/ui/dist/copy/tree/runtime/chunks/advanced-BrFnVc0y.js delete mode 100644 packages/ui/dist/copy/tree/runtime/chunks/advanced-CqBF0dSb.js delete mode 100644 packages/ui/dist/copy/tree/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/tree/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/tree/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/tree/runtime/chunks/element-Dovcr9Ky.js create mode 100644 packages/ui/dist/copy/tree/runtime/chunks/markup-AopKpwOF.js delete mode 100644 packages/ui/dist/copy/tree/runtime/chunks/markup-DeQ4bEMR.js delete mode 100644 packages/ui/dist/copy/wizard/runtime/chunks/choice-B7mo5Eq3.js create mode 100644 packages/ui/dist/copy/wizard/runtime/chunks/choice-DqwWT5pJ.js create mode 100644 packages/ui/dist/copy/wizard/runtime/chunks/element-DcrNU9Wh.js delete mode 100644 packages/ui/dist/copy/wizard/runtime/chunks/element-Dovcr9Ky.js rename packages/ui/dist/copy/wizard/runtime/chunks/{forms-CE_hP1hg.js => forms-C3u5121t.js} (96%) diff --git a/package-lock.json b/package-lock.json index 7b5e0d7f4..6438d2999 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "@vitejs/plugin-vue": "6.0.10", "astro": "7.4.2", "es-module-lexer": "3.0.4", + "esbuild": "0.28.2", "fflate": "0.8.3", "jsonc-parser": "3.3.1", "parse5": "8.0.1", @@ -685,6 +686,422 @@ "tslib": "^2.4.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@img/colour": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", @@ -3211,6 +3628,48 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/esbuild": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "devOptional": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, "node_modules/escape-string-regexp": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", diff --git a/package.json b/package.json index 85e366615..374e8f918 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "@vitejs/plugin-vue": "6.0.10", "astro": "7.4.2", "es-module-lexer": "3.0.4", + "esbuild": "0.28.2", "fflate": "0.8.3", "jsonc-parser": "3.3.1", "parse5": "8.0.1", diff --git a/packages/ui/dist/chunks/advanced-CqBF0dSb.js b/packages/ui/dist/chunks/advanced-BrFnVc0y.js similarity index 98% rename from packages/ui/dist/chunks/advanced-CqBF0dSb.js rename to packages/ui/dist/chunks/advanced-BrFnVc0y.js index 4a5c45981..36e7638c4 100644 --- a/packages/ui/dist/chunks/advanced-CqBF0dSb.js +++ b/packages/ui/dist/chunks/advanced-BrFnVc0y.js @@ -1,6 +1,6 @@ -import { c as keyIndex, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-B7mo5Eq3.js"; -import { t as IDREFS } from "./markup-DeQ4bEMR.js"; -//#region packages/ui/src/behaviors/advanced.js +import { c as keyIndex, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-DqwWT5pJ.js"; +import { t as IDREFS } from "./markup-AopKpwOF.js"; +// packages/ui/src/behaviors/advanced.js function tree(root, { on }) { const treeRoot = root.querySelector("[role=\"tree\"]"); if (!treeRoot) return {}; @@ -341,5 +341,4 @@ function commandPalette(root, { on }) { cleanup: close }; } -//#endregion export { tree as i, multiselect as n, repeater as r, commandPalette as t }; diff --git a/packages/ui/dist/copy/admin-form/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/chunks/choice-DqwWT5pJ.js similarity index 99% rename from packages/ui/dist/copy/admin-form/runtime/chunks/choice-B7mo5Eq3.js rename to packages/ui/dist/chunks/choice-DqwWT5pJ.js index 849c80b8b..a20d3e3f6 100644 --- a/packages/ui/dist/copy/admin-form/runtime/chunks/choice-B7mo5Eq3.js +++ b/packages/ui/dist/chunks/choice-DqwWT5pJ.js @@ -1,4 +1,4 @@ -//#region packages/ui/src/internal/dom.js +// packages/ui/src/internal/dom.js var all = (root, selector) => [...root.querySelectorAll(selector)]; var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; var visible = (node) => !node.closest("[hidden]"); @@ -88,8 +88,7 @@ function place(trigger, popup) { overflowY: "auto" }); } -//#endregion -//#region packages/ui/src/internal/temporal.js +// packages/ui/src/internal/temporal.js var instances = /* @__PURE__ */ new WeakMap(); var sequence$1 = 0; function mountTemporal(input) { @@ -518,8 +517,7 @@ function mountTemporal(input) { instances.set(input, api); return api; } -//#endregion -//#region packages/ui/src/internal/choice.js +// packages/ui/src/internal/choice.js var mounted = /* @__PURE__ */ new WeakMap(); var sequence = 0; function mountChoice(select) { @@ -934,5 +932,4 @@ function enhanceControls(root) { } }; } -//#endregion export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/compositions-D57dCsBz.js b/packages/ui/dist/chunks/compositions-DWG4tv9E.js similarity index 91% rename from packages/ui/dist/copy/compact-dashboard/runtime/chunks/compositions-D57dCsBz.js rename to packages/ui/dist/chunks/compositions-DWG4tv9E.js index f1da4562e..aa98d384a 100644 --- a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/compositions-D57dCsBz.js +++ b/packages/ui/dist/chunks/compositions-DWG4tv9E.js @@ -1,6 +1,6 @@ -import { i as all, o as enabled } from "./choice-B7mo5Eq3.js"; -import { i as tabs } from "./navigation-BfNzDYZB.js"; -//#region packages/ui/src/behaviors/compositions.js +import { i as all, o as enabled } from "./choice-DqwWT5pJ.js"; +import { i as tabs } from "./navigation-CknoksQ5.js"; +// packages/ui/src/behaviors/compositions.js function fileBrowser(root, { on }) { const query = root.querySelector("[data-file-query]"), rows = all(root, "tr[data-file-id]"), status = root.querySelector("[data-file-status]"); let location = "all"; @@ -47,5 +47,4 @@ function windowFrame(root, context) { }); return {}; } -//#endregion export { fileBrowser as n, windowFrame as r, dashboard as t }; diff --git a/packages/ui/dist/copy/chart/runtime/chunks/display-Jm9bAsnb.js b/packages/ui/dist/chunks/display-l54fb8vw.js similarity index 98% rename from packages/ui/dist/copy/chart/runtime/chunks/display-Jm9bAsnb.js rename to packages/ui/dist/chunks/display-l54fb8vw.js index 5bc817830..b2f57aaf2 100644 --- a/packages/ui/dist/copy/chart/runtime/chunks/display-Jm9bAsnb.js +++ b/packages/ui/dist/chunks/display-l54fb8vw.js @@ -1,5 +1,5 @@ -import { i as all, l as make, o as enabled } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/display.js +import { i as all, l as make, o as enabled } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/display.js function avatar(root, { on }) { const frame = root.querySelector(".avatar"), fallback = root.querySelector("[data-avatar-fallback]"); if (!frame || !fallback) return {}; @@ -208,5 +208,4 @@ function developerView(root, { on }) { pre.textContent = String(text); } }; } -//#endregion export { editorSearch as i, chart as n, developerView as r, avatar as t }; diff --git a/packages/ui/dist/copy/alert/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/chunks/element-DcrNU9Wh.js similarity index 98% rename from packages/ui/dist/copy/alert/runtime/chunks/element-Dovcr9Ky.js rename to packages/ui/dist/chunks/element-DcrNU9Wh.js index aa7a67cb4..86fb43da9 100644 --- a/packages/ui/dist/copy/alert/runtime/chunks/element-Dovcr9Ky.js +++ b/packages/ui/dist/chunks/element-DcrNU9Wh.js @@ -1,5 +1,5 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js var HTMLElementBase = globalThis.HTMLElement ?? class {}; var nextInstance = 0; var J3w1Element = class extends HTMLElementBase { @@ -228,5 +228,4 @@ function registerElement(name, Constructor, registry = globalThis.customElements if (!current) registry.define(name, Constructor); return current ?? Constructor; } -//#endregion export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/chunks/form-builder-BvWZCBPR.js b/packages/ui/dist/chunks/form-builder-CkeTBQe-.js similarity index 82% rename from packages/ui/dist/chunks/form-builder-BvWZCBPR.js rename to packages/ui/dist/chunks/form-builder-CkeTBQe-.js index a14d0d676..d749d2eba 100644 --- a/packages/ui/dist/chunks/form-builder-BvWZCBPR.js +++ b/packages/ui/dist/chunks/form-builder-CkeTBQe-.js @@ -1,6 +1,6 @@ -import { t as J3w1Element } from "./element-Dovcr9Ky.js"; -import { t as mountBuilder } from "./form-builder-BRIaVVFY.js"; -//#region packages/ui/src/behaviors/form-builder.js +import { t as J3w1Element } from "./element-DcrNU9Wh.js"; +import { t as mountBuilder } from "./form-builder-DbZUZMo1.js"; +// packages/ui/src/behaviors/form-builder.js function formBuilder(root, { signal }) { const editor = root.querySelector("[data-builder]"); if (!editor) throw new Error("The form builder requires the complete maintained editor and preview markup"); @@ -17,12 +17,11 @@ function formBuilder(root, { signal }) { cleanup: api.destroy }; } -//#endregion -//#region .cache/ui-build/entries/components/form-builder.js +// .cache/ui-build/entries/components/form-builder.js var J3w1FormBuilder = class extends J3w1Element { static componentId = "form-builder"; static version = "4.0.0"; - static implementationId = "sha256-dFrLEZ4jQ0jq5jBzJdmUBQ8504+zDzvRQmhv59pmQs4="; + static implementationId = "sha256-FO3zSzWMChoC10L1NZoNUpgmEHttCO6FI00qTLTik28="; static connect = formBuilder; static upgradeProperties = [ "disabled", @@ -50,5 +49,4 @@ var J3w1FormBuilder = class extends J3w1Element { }); } }; -//#endregion export { J3w1FormBuilder as t }; diff --git a/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-BRIaVVFY.js b/packages/ui/dist/chunks/form-builder-DbZUZMo1.js similarity index 99% rename from packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-BRIaVVFY.js rename to packages/ui/dist/chunks/form-builder-DbZUZMo1.js index afa6bc088..b9f3ff528 100644 --- a/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-BRIaVVFY.js +++ b/packages/ui/dist/chunks/form-builder-DbZUZMo1.js @@ -1,5 +1,5 @@ -import { a as FORM_LIMITS, i as FIELD_TYPES, n as emptyValues, r as parseFormSchema, t as mountWorkflow } from "./form-workflow-BKRLylvq.js"; -//#region scripts/lib/form-builder.mjs +import { a as FORM_LIMITS, i as FIELD_TYPES, n as emptyValues, r as parseFormSchema, t as mountWorkflow } from "./form-workflow-B183Y5gc.js"; +// scripts/lib/form-builder.mjs var createBuilder = (theme) => ({ definition: { schemaVersion: 1, @@ -71,8 +71,7 @@ var identity_default = { profile: "default", sourceDigest: "sha256-gSQ1VcVNkjVKCkTGXt6fbWGqvDCJTpGQsFjWGbriWi0=" }; -//#endregion -//#region packages/ui/src/internal/form-builder.js +// packages/ui/src/internal/form-builder.js var templates = { schemaVersion: 1, version: "4.0.0", @@ -248,5 +247,4 @@ var mountBuilder = (root, { signal } = {}) => { } }; }; -//#endregion export { mountBuilder as t }; diff --git a/packages/ui/dist/chunks/form-workflow-BKRLylvq.js b/packages/ui/dist/chunks/form-workflow-B183Y5gc.js similarity index 99% rename from packages/ui/dist/chunks/form-workflow-BKRLylvq.js rename to packages/ui/dist/chunks/form-workflow-B183Y5gc.js index 6ef25ba0b..185b472b6 100644 --- a/packages/ui/dist/chunks/form-workflow-BKRLylvq.js +++ b/packages/ui/dist/chunks/form-workflow-B183Y5gc.js @@ -1,5 +1,5 @@ -import { a as setAttribute, i as removeAttribute, n as hasClass, o as walkMarkup, r as namespaceMarkup } from "./markup-DeQ4bEMR.js"; -//#region \0rolldown/runtime.js +import { a as setAttribute, i as removeAttribute, n as hasClass, o as walkMarkup, r as namespaceMarkup } from "./markup-AopKpwOF.js"; +// \0rolldown/runtime.js var __defProp = Object.defineProperty; var __exportAll = (all, no_symbols) => { let target = {}; @@ -10,8 +10,7 @@ var __exportAll = (all, no_symbols) => { if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" }); return target; }; -//#endregion -//#region node_modules/zod/v4/core/util.js +// node_modules/zod/v4/core/util.js var util_exports = /* @__PURE__ */ __exportAll({ BIGINT_FORMAT_RANGES: () => BIGINT_FORMAT_RANGES, CONSTANT_CATCH: () => CONSTANT_CATCH, @@ -81,6 +80,7 @@ var util_exports = /* @__PURE__ */ __exportAll({ required: () => required, safeExtend: () => safeExtend, shallowClone: () => shallowClone, + sizeCaps: () => sizeCaps, slugify: () => slugify, stringifyPrimitive: () => stringifyPrimitive, toZod: () => toZod, @@ -520,6 +520,17 @@ function prefixIssues(path, issues) { function unwrapMessage(message) { return typeof message === "string" ? message : message?.message; } +/** The leading size checks of `defChecks` that set an upper bound, each paired with it. */ +function sizeCaps(defChecks) { + const caps = []; + for (const ch of defChecks ?? []) { + const d = ch._zod.def; + if (!/_(length|size)$|_equals$/.test(d.check)) break; + const max = d.maximum ?? d.length ?? d.size; + if (max >= 0) caps.push([max, ch]); + } + return caps; +} function attachSchema(issues, start, inst) { var _a; for (let i = start; i < issues.length; i++) (_a = issues[i]).schema ?? (_a.schema = inst); @@ -654,6 +665,7 @@ function hide(inst, key, value) { return own(inst, key, value, false); } /** Adds members a table derives from the instance: each builds on first read and shadows as own data, and assignment shadows the same way, as when these were own properties. */ +/* @__NO_SIDE_EFFECTS__ */ function derived(computes, table) { for (const key in computes) { const compute = computes[key]; @@ -777,8 +789,7 @@ function constantCatch(value) { fn[CONSTANT_CATCH] = true; return fn; } -//#endregion -//#region node_modules/zod/v4/core/core.js +// node_modules/zod/v4/core/core.js var _a$1; /** A special constant with type `never` */ var NEVER = /*@__PURE__*/ Object.freeze({ status: "aborted" }); @@ -807,6 +818,7 @@ function newError(Definition) { } return new Definition(); } +/* @__NO_SIDE_EFFECTS__ */ function $constructor(name, initializer, proto, params) { const zodProto = {}; function Internals(def) { @@ -886,8 +898,7 @@ function config(newConfig) { if (newConfig) Object.assign(globalConfig, newConfig); return globalConfig; } -//#endregion -//#region node_modules/zod/v4/core/errors.js +// node_modules/zod/v4/core/errors.js function _getMessage() { const internals = this._zod; internals.message ?? (internals.message = JSON.stringify(internals.def, jsonStringifyReplacer, 2)); @@ -938,8 +949,8 @@ var initializer$1 = (inst, def) => { }); } }; -var $ZodError = $constructor("$ZodError", initializer$1); -var $ZodRealError = $constructor("$ZodError", initializer$1, void 0, { Parent: Error }); +var $ZodError = /* @__PURE__ */ $constructor("$ZodError", initializer$1); +var $ZodRealError = /* @__PURE__ */ $constructor("$ZodError", initializer$1, void 0, { Parent: Error }); /** Get-or-create `obj[key]` as an own data property. A path segment naming an inherited member * ("toString", "constructor") would otherwise read through to the prototype, and assigning * "__proto__" would hit the setter instead of creating a key. */ @@ -1095,8 +1106,7 @@ function prettifyError(error) { } return lines.join("\n"); } -//#endregion -//#region node_modules/zod/v4/core/parse.js +// node_modules/zod/v4/core/parse.js function finalizeParams(callee, params) { return { callee: params?.callee ?? callee, @@ -1310,8 +1320,7 @@ var _safeDecodeAsync = (_Err) => async (schema, value, _ctx) => { return _safeParseAsync(_Err)(schema, value, _ctx); }; var safeDecodeAsync$1 = /* @__PURE__*/ _safeDecodeAsync($ZodRealError); -//#endregion -//#region node_modules/zod/v4/core/regexes.js +// node_modules/zod/v4/core/regexes.js var regexes_exports = /* @__PURE__ */ __exportAll({ anyString: () => anyString, base64: () => base64$1, @@ -1499,8 +1508,7 @@ var sha384_base64url = /*@__PURE__*/ fixedBase64url(64); var sha512_hex = /^[0-9a-fA-F]{128}$/; var sha512_base64 = /*@__PURE__*/ fixedBase64(86, "=="); var sha512_base64url = /*@__PURE__*/ fixedBase64url(86); -//#endregion -//#region node_modules/zod/v4/core/checks.js +// node_modules/zod/v4/core/checks.js var $ZodCheck = /*@__PURE__*/ $constructor("$ZodCheck", (inst, def) => { var _a; inst._zod ?? (inst._zod = {}); @@ -1947,8 +1955,7 @@ var $ZodCheckOverwrite = /*@__PURE__*/ $constructor("$ZodCheckOverwrite", (inst, payload.value = def.tx(payload.value); }; }); -//#endregion -//#region node_modules/zod/v4/core/doc.js +// node_modules/zod/v4/core/doc.js var Doc = class { constructor(args = [], closed = {}) { this.content = []; @@ -1981,15 +1988,13 @@ var Doc = class { return new F(...Object.keys(this.closed), `return function (${this.args.join(", ")}) {\n${content.join("\n")}\n};`)(...Object.values(this.closed)); } }; -//#endregion -//#region node_modules/zod/v4/core/versions.js +// node_modules/zod/v4/core/versions.js var version = { major: 4, minor: 6, - patch: 5 + patch: 7 }; -//#endregion -//#region node_modules/zod/v4/core/schemas.js +// node_modules/zod/v4/core/schemas.js var $ZodType = /*@__PURE__*/ $constructor("$ZodType", (inst, def) => { var _a; inst ?? (inst = {}); @@ -2680,6 +2685,28 @@ var $ZodDate = /*@__PURE__*/ $constructor("$ZodDate", (inst, def) => { return payload; }; }); +function capSize(inst, size) { + const caps = sizeCaps(inst._zod.def.checks); + if (!caps.length) return; + const cap = Math.min(...caps.map((c) => c[0])); + const parse = inst._zod.parse; + inst._zod.parse = (payload, ctx) => { + const n = size(payload.value); + if (n > cap && !ctx?.skipChecks && ctx?.direction !== "backward") { + for (const [max, ch] of sizeCaps(inst._zod.def.checks)) if (n > max && ch._zod.def.when(payload)) { + const start = payload.issues.length; + ch._zod.check(payload); + payload.issues[start].continue = false; + attachSchema(payload.issues, start, inst); + return payload; + } + } + return parse(payload, ctx); + }; +} +var arraySize = (input) => Array.isArray(input) ? input.length : -1; +var mapSize = (input) => input instanceof Map ? input.size : -1; +var setSize = (input) => input instanceof Set ? input.size : -1; function handleArrayResult(result, final, index) { if (result.issues.length) final.issues.push(...prefixIssues(index, result.issues)); final.value[index] = result.value; @@ -2717,6 +2744,7 @@ var $ZodArray = /*@__PURE__*/ $constructor("$ZodArray", (inst, def) => { if (proms.length) return Promise.all(proms).then(() => payload); return payload; }; + capSize(inst, arraySize); }); function handlePropertyResult(result, final, key, input, optin, optout) { const isPresent = key in input; @@ -2825,7 +2853,7 @@ var $ZodObject = /*@__PURE__*/ $constructor("$ZodObject", (inst, def) => { } return propValues; }); - const isObject$2 = isObject; + const isObject$1 = isObject; const catchall = def.catchall; let value; const memo = globalConfig.memoizer; @@ -2833,7 +2861,7 @@ var $ZodObject = /*@__PURE__*/ $constructor("$ZodObject", (inst, def) => { inst._zod.parse = (payload, ctx) => { value ?? (value = _normalized.value); const input = payload.value; - if (!isObject$2(input)) { + if (!isObject$1(input)) { payload.issues.push({ expected: "object", code: "invalid_type", @@ -2963,7 +2991,7 @@ var $ZodObjectJIT = /*@__PURE__*/ $constructor("$ZodObjectJIT", (inst, def) => { return doc.compile(); }; let fastpass; - const isObject$1 = isObject; + const isObject$2 = isObject; const jit = !globalConfig.jitless; const fastEnabled = jit && allowsEval.value; const catchall = def.catchall; @@ -2971,7 +2999,7 @@ var $ZodObjectJIT = /*@__PURE__*/ $constructor("$ZodObjectJIT", (inst, def) => { inst._zod.parse = (payload, ctx) => { value ?? (value = _normalized.value); const input = payload.value; - if (!isObject$1(input)) { + if (!isObject$2(input)) { payload.issues.push({ expected: "object", code: "invalid_type", @@ -3561,6 +3589,7 @@ var $ZodMap = /*@__PURE__*/ $constructor("$ZodMap", (inst, def) => { if (proms.length) return Promise.all(proms).then(() => payload); return payload; }; + capSize(inst, mapSize); }); function handleMapResult(keyResult, valueResult, final, key, input, inst, ctx) { if (keyResult.issues.length) { @@ -3620,6 +3649,7 @@ var $ZodSet = /*@__PURE__*/ $constructor("$ZodSet", (inst, def) => { if (proms.length) return Promise.all(proms).then(() => payload); return payload; }; + capSize(inst, setSize); }); function handleSetResult(result, final) { if (result.issues.length) final.issues.push(...result.issues); @@ -4142,8 +4172,7 @@ function handleRefineResult(result, payload, input, inst) { payload.issues.push(issue(_iss)); } } -//#endregion -//#region node_modules/zod/v4/core/memoizer.js +// node_modules/zod/v4/core/memoizer.js var $ZodCyclicError = class extends Error { constructor() { super(`Cannot parse a reference cycle that closes through a transform`); @@ -4404,8 +4433,7 @@ function isBackEdge(ctx, value) { const backEdges = ctx[STATE]?.backEdges; return backEdges !== void 0 && isRef(value) && backEdges.has(value); } -//#endregion -//#region node_modules/zod/v4/locales/ar.js +// node_modules/zod/v4/locales/ar.js var error$60 = () => { const Sizable = { string: { @@ -4511,8 +4539,7 @@ var error$60 = () => { function ar_default() { return { localeError: error$60() }; } -//#endregion -//#region node_modules/zod/v4/locales/az.js +// node_modules/zod/v4/locales/az.js var error$59 = () => { const Sizable = { string: { @@ -4618,8 +4645,7 @@ var error$59 = () => { function az_default() { return { localeError: error$59() }; } -//#endregion -//#region node_modules/zod/v4/locales/be.js +// node_modules/zod/v4/locales/be.js function getBelarusianPlural(count, one, few, many) { const absCount = Math.abs(count); const lastDigit = absCount % 10; @@ -4764,8 +4790,7 @@ var error$58 = () => { function be_default() { return { localeError: error$58() }; } -//#endregion -//#region node_modules/zod/v4/locales/bg.js +// node_modules/zod/v4/locales/bg.js var error$57 = () => { const Sizable = { string: { @@ -4881,8 +4906,7 @@ var error$57 = () => { function bg_default() { return { localeError: error$57() }; } -//#endregion -//#region node_modules/zod/v4/locales/bn.js +// node_modules/zod/v4/locales/bn.js var error$56 = () => { const Sizable = { string: { @@ -4988,8 +5012,7 @@ var error$56 = () => { function bn_default() { return { localeError: error$56() }; } -//#endregion -//#region node_modules/zod/v4/locales/ca.js +// node_modules/zod/v4/locales/ca.js var error$55 = () => { const Sizable = { string: { @@ -5095,8 +5118,7 @@ var error$55 = () => { function ca_default() { return { localeError: error$55() }; } -//#endregion -//#region node_modules/zod/v4/locales/ckb.js +// node_modules/zod/v4/locales/ckb.js var error$54 = () => { const Sizable = { string: { @@ -5232,8 +5254,7 @@ var error$54 = () => { function ckb_default() { return { localeError: error$54() }; } -//#endregion -//#region node_modules/zod/v4/locales/cs.js +// node_modules/zod/v4/locales/cs.js var error$53 = () => { const Sizable = { string: { @@ -5345,8 +5366,7 @@ var error$53 = () => { function cs_default() { return { localeError: error$53() }; } -//#endregion -//#region node_modules/zod/v4/locales/da.js +// node_modules/zod/v4/locales/da.js var error$52 = () => { const Sizable = { string: { @@ -5463,8 +5483,7 @@ var error$52 = () => { function da_default() { return { localeError: error$52() }; } -//#endregion -//#region node_modules/zod/v4/locales/de.js +// node_modules/zod/v4/locales/de.js var error$51 = () => { const Sizable = { string: { @@ -5574,8 +5593,7 @@ var error$51 = () => { function de_default() { return { localeError: error$51() }; } -//#endregion -//#region node_modules/zod/v4/locales/el.js +// node_modules/zod/v4/locales/el.js var error$50 = () => { const Sizable = { string: { @@ -5681,8 +5699,7 @@ var error$50 = () => { function el_default() { return { localeError: error$50() }; } -//#endregion -//#region node_modules/zod/v4/locales/en.js +// node_modules/zod/v4/locales/en.js var error$49 = () => { const Sizable = { string: { @@ -5789,8 +5806,7 @@ var error$49 = () => { function en_default() { return { localeError: error$49() }; } -//#endregion -//#region node_modules/zod/v4/locales/eo.js +// node_modules/zod/v4/locales/eo.js var error$48 = () => { const Sizable = { string: { @@ -5901,8 +5917,7 @@ var error$48 = () => { function eo_default() { return { localeError: error$48() }; } -//#endregion -//#region node_modules/zod/v4/locales/es.js +// node_modules/zod/v4/locales/es.js var error$47 = () => { const Sizable = { string: { @@ -6032,8 +6047,7 @@ var error$47 = () => { function es_default() { return { localeError: error$47() }; } -//#endregion -//#region node_modules/zod/v4/locales/fa.js +// node_modules/zod/v4/locales/fa.js var error$46 = () => { const Sizable = { string: { @@ -6143,8 +6157,7 @@ var error$46 = () => { function fa_default() { return { localeError: error$46() }; } -//#endregion -//#region node_modules/zod/v4/locales/fi.js +// node_modules/zod/v4/locales/fi.js var error$45 = () => { const Sizable = { string: { @@ -6266,8 +6279,7 @@ var error$45 = () => { function fi_default() { return { localeError: error$45() }; } -//#endregion -//#region node_modules/zod/v4/locales/fr.js +// node_modules/zod/v4/locales/fr.js var error$44 = () => { const Sizable = { string: { @@ -6391,8 +6403,7 @@ var error$44 = () => { function fr_default() { return { localeError: error$44() }; } -//#endregion -//#region node_modules/zod/v4/locales/fr-CA.js +// node_modules/zod/v4/locales/fr-CA.js var error$43 = () => { const Sizable = { string: { @@ -6498,8 +6509,7 @@ var error$43 = () => { function fr_CA_default() { return { localeError: error$43() }; } -//#endregion -//#region node_modules/zod/v4/locales/gu.js +// node_modules/zod/v4/locales/gu.js var error$42 = () => { const Sizable = { string: { @@ -6605,8 +6615,7 @@ var error$42 = () => { function gu_default() { return { localeError: error$42() }; } -//#endregion -//#region node_modules/zod/v4/locales/he.js +// node_modules/zod/v4/locales/he.js var error$41 = () => { const TypeNames = { string: { @@ -6938,8 +6947,7 @@ var error$41 = () => { function he_default() { return { localeError: error$41() }; } -//#endregion -//#region node_modules/zod/v4/locales/hi.js +// node_modules/zod/v4/locales/hi.js var error$40 = () => { const Sizable = { string: { @@ -7045,8 +7053,7 @@ var error$40 = () => { function hi_default() { return { localeError: error$40() }; } -//#endregion -//#region node_modules/zod/v4/locales/hr.js +// node_modules/zod/v4/locales/hr.js var error$39 = () => { const Sizable = { string: { @@ -7166,8 +7173,7 @@ var error$39 = () => { function hr_default() { return { localeError: error$39() }; } -//#endregion -//#region node_modules/zod/v4/locales/hu.js +// node_modules/zod/v4/locales/hu.js var error$38 = () => { const Sizable = { string: { @@ -7277,8 +7283,7 @@ var error$38 = () => { function hu_default() { return { localeError: error$38() }; } -//#endregion -//#region node_modules/zod/v4/locales/hy.js +// node_modules/zod/v4/locales/hy.js function getArmenianPlural(count, one, many) { return Math.abs(count) === 1 ? one : many; } @@ -7426,8 +7431,7 @@ var error$37 = () => { function hy_default() { return { localeError: error$37() }; } -//#endregion -//#region node_modules/zod/v4/locales/id.js +// node_modules/zod/v4/locales/id.js var error$36 = () => { const Sizable = { string: { @@ -7533,8 +7537,7 @@ var error$36 = () => { function id_default() { return { localeError: error$36() }; } -//#endregion -//#region node_modules/zod/v4/locales/is.js +// node_modules/zod/v4/locales/is.js var error$35 = () => { const Sizable = { string: { @@ -7644,8 +7647,7 @@ var error$35 = () => { function is_default() { return { localeError: error$35() }; } -//#endregion -//#region node_modules/zod/v4/locales/it.js +// node_modules/zod/v4/locales/it.js var error$34 = () => { const Sizable = { string: { @@ -7755,8 +7757,7 @@ var error$34 = () => { function it_default() { return { localeError: error$34() }; } -//#endregion -//#region node_modules/zod/v4/locales/ja.js +// node_modules/zod/v4/locales/ja.js var error$33 = () => { const Sizable = { string: { @@ -7866,8 +7867,7 @@ var error$33 = () => { function ja_default() { return { localeError: error$33() }; } -//#endregion -//#region node_modules/zod/v4/locales/ka.js +// node_modules/zod/v4/locales/ka.js var error$32 = () => { const Sizable = { string: { @@ -7980,8 +7980,7 @@ var error$32 = () => { function ka_default() { return { localeError: error$32() }; } -//#endregion -//#region node_modules/zod/v4/locales/km.js +// node_modules/zod/v4/locales/km.js var error$31 = () => { const Sizable = { string: { @@ -8092,14 +8091,12 @@ var error$31 = () => { function km_default() { return { localeError: error$31() }; } -//#endregion -//#region node_modules/zod/v4/locales/kh.js +// node_modules/zod/v4/locales/kh.js /** @deprecated Use `km` instead. */ function kh_default() { return km_default(); } -//#endregion -//#region node_modules/zod/v4/locales/kn.js +// node_modules/zod/v4/locales/kn.js var error$30 = () => { const Sizable = { string: { @@ -8205,8 +8202,7 @@ var error$30 = () => { function kn_default() { return { localeError: error$30() }; } -//#endregion -//#region node_modules/zod/v4/locales/ko.js +// node_modules/zod/v4/locales/ko.js var error$29 = () => { const Sizable = { string: { @@ -8316,8 +8312,7 @@ var error$29 = () => { function ko_default() { return { localeError: error$29() }; } -//#endregion -//#region node_modules/zod/v4/locales/lt.js +// node_modules/zod/v4/locales/lt.js var capitalizeFirstCharacter = (text) => { return text.charAt(0).toUpperCase() + text.slice(1); }; @@ -8501,8 +8496,7 @@ var error$28 = () => { function lt_default() { return { localeError: error$28() }; } -//#endregion -//#region node_modules/zod/v4/locales/mk.js +// node_modules/zod/v4/locales/mk.js var error$27 = () => { const Sizable = { string: { @@ -8612,8 +8606,7 @@ var error$27 = () => { function mk_default() { return { localeError: error$27() }; } -//#endregion -//#region node_modules/zod/v4/locales/ms.js +// node_modules/zod/v4/locales/ms.js var error$26 = () => { const Sizable = { string: { @@ -8722,8 +8715,7 @@ var error$26 = () => { function ms_default() { return { localeError: error$26() }; } -//#endregion -//#region node_modules/zod/v4/locales/ne.js +// node_modules/zod/v4/locales/ne.js var error$25 = () => { const Sizable = { string: { @@ -8829,8 +8821,7 @@ var error$25 = () => { function ne_default() { return { localeError: error$25() }; } -//#endregion -//#region node_modules/zod/v4/locales/nl.js +// node_modules/zod/v4/locales/nl.js var error$24 = () => { const Sizable = { string: { @@ -8941,8 +8932,7 @@ var error$24 = () => { function nl_default() { return { localeError: error$24() }; } -//#endregion -//#region node_modules/zod/v4/locales/nn.js +// node_modules/zod/v4/locales/nn.js var error$23 = () => { const Sizable = { string: { @@ -9052,8 +9042,7 @@ var error$23 = () => { function nn_default() { return { localeError: error$23() }; } -//#endregion -//#region node_modules/zod/v4/locales/no.js +// node_modules/zod/v4/locales/no.js var error$22 = () => { const Sizable = { string: { @@ -9163,8 +9152,7 @@ var error$22 = () => { function no_default() { return { localeError: error$22() }; } -//#endregion -//#region node_modules/zod/v4/locales/ota.js +// node_modules/zod/v4/locales/ota.js var error$21 = () => { const Sizable = { string: { @@ -9275,8 +9263,7 @@ var error$21 = () => { function ota_default() { return { localeError: error$21() }; } -//#endregion -//#region node_modules/zod/v4/locales/ps.js +// node_modules/zod/v4/locales/ps.js var error$20 = () => { const Sizable = { string: { @@ -9386,8 +9373,7 @@ var error$20 = () => { function ps_default() { return { localeError: error$20() }; } -//#endregion -//#region node_modules/zod/v4/locales/pl.js +// node_modules/zod/v4/locales/pl.js var error$19 = () => { const Sizable = { string: { @@ -9497,8 +9483,7 @@ var error$19 = () => { function pl_default() { return { localeError: error$19() }; } -//#endregion -//#region node_modules/zod/v4/locales/pt.js +// node_modules/zod/v4/locales/pt.js var error$18 = () => { const Sizable = { string: { unit: "caracteres" }, @@ -9690,8 +9675,7 @@ var error$18 = () => { function pt_default() { return { localeError: error$18() }; } -//#endregion -//#region node_modules/zod/v4/locales/pt-BR.js +// node_modules/zod/v4/locales/pt-BR.js var error$17 = () => { const Sizable = { string: { unit: "caracteres" }, @@ -9883,8 +9867,7 @@ var error$17 = () => { function pt_BR_default() { return { localeError: error$17() }; } -//#endregion -//#region node_modules/zod/v4/locales/ro.js +// node_modules/zod/v4/locales/ro.js var error$16 = () => { const Sizable = { string: { @@ -10003,8 +9986,7 @@ var error$16 = () => { function ro_default() { return { localeError: error$16() }; } -//#endregion -//#region node_modules/zod/v4/locales/ru.js +// node_modules/zod/v4/locales/ru.js function getRussianPlural(count, one, few, many) { const absCount = Math.abs(count); const lastDigit = absCount % 10; @@ -10149,8 +10131,7 @@ var error$15 = () => { function ru_default() { return { localeError: error$15() }; } -//#endregion -//#region node_modules/zod/v4/locales/sk.js +// node_modules/zod/v4/locales/sk.js var error$14 = () => { const Sizable = { string: { @@ -10262,8 +10243,7 @@ var error$14 = () => { function sk_default() { return { localeError: error$14() }; } -//#endregion -//#region node_modules/zod/v4/locales/sl.js +// node_modules/zod/v4/locales/sl.js var error$13 = () => { const Sizable = { string: { @@ -10373,8 +10353,7 @@ var error$13 = () => { function sl_default() { return { localeError: error$13() }; } -//#endregion -//#region node_modules/zod/v4/locales/sv.js +// node_modules/zod/v4/locales/sv.js var error$12 = () => { const Sizable = { string: { @@ -10484,8 +10463,7 @@ var error$12 = () => { function sv_default() { return { localeError: error$12() }; } -//#endregion -//#region node_modules/zod/v4/locales/ta.js +// node_modules/zod/v4/locales/ta.js var error$11 = () => { const Sizable = { string: { @@ -10596,8 +10574,7 @@ var error$11 = () => { function ta_default() { return { localeError: error$11() }; } -//#endregion -//#region node_modules/zod/v4/locales/tg.js +// node_modules/zod/v4/locales/tg.js var error$10 = () => { const Sizable = { string: { @@ -10710,8 +10687,7 @@ var error$10 = () => { function tg_default() { return { localeError: error$10() }; } -//#endregion -//#region node_modules/zod/v4/locales/th.js +// node_modules/zod/v4/locales/th.js var error$9 = () => { const Sizable = { string: { @@ -10822,8 +10798,7 @@ var error$9 = () => { function th_default() { return { localeError: error$9() }; } -//#endregion -//#region node_modules/zod/v4/locales/tk.js +// node_modules/zod/v4/locales/tk.js var error$8 = () => { const Sizable = { string: { @@ -10927,8 +10902,7 @@ var error$8 = () => { function tk_default() { return { localeError: error$8() }; } -//#endregion -//#region node_modules/zod/v4/locales/tr.js +// node_modules/zod/v4/locales/tr.js var error$7 = () => { const Sizable = { string: { @@ -11034,8 +11008,7 @@ var error$7 = () => { function tr_default() { return { localeError: error$7() }; } -//#endregion -//#region node_modules/zod/v4/locales/uk.js +// node_modules/zod/v4/locales/uk.js var error$6 = () => { const Sizable = { string: { @@ -11145,14 +11118,12 @@ var error$6 = () => { function uk_default() { return { localeError: error$6() }; } -//#endregion -//#region node_modules/zod/v4/locales/ua.js +// node_modules/zod/v4/locales/ua.js /** @deprecated Use `uk` instead. */ function ua_default() { return uk_default(); } -//#endregion -//#region node_modules/zod/v4/locales/ur.js +// node_modules/zod/v4/locales/ur.js var error$5 = () => { const Sizable = { string: { @@ -11263,8 +11234,7 @@ var error$5 = () => { function ur_default() { return { localeError: error$5() }; } -//#endregion -//#region node_modules/zod/v4/locales/uz.js +// node_modules/zod/v4/locales/uz.js var error$4 = () => { const Sizable = { string: { @@ -11374,8 +11344,7 @@ var error$4 = () => { function uz_default() { return { localeError: error$4() }; } -//#endregion -//#region node_modules/zod/v4/locales/vi.js +// node_modules/zod/v4/locales/vi.js var error$3 = () => { const Sizable = { string: { @@ -11485,8 +11454,7 @@ var error$3 = () => { function vi_default() { return { localeError: error$3() }; } -//#endregion -//#region node_modules/zod/v4/locales/zh-CN.js +// node_modules/zod/v4/locales/zh-CN.js var error$2 = () => { const Sizable = { string: { @@ -11597,8 +11565,7 @@ var error$2 = () => { function zh_CN_default() { return { localeError: error$2() }; } -//#endregion -//#region node_modules/zod/v4/locales/zh-TW.js +// node_modules/zod/v4/locales/zh-TW.js var error$1 = () => { const Sizable = { string: { @@ -11704,8 +11671,7 @@ var error$1 = () => { function zh_TW_default() { return { localeError: error$1() }; } -//#endregion -//#region node_modules/zod/v4/locales/yo.js +// node_modules/zod/v4/locales/yo.js var error = () => { const Sizable = { string: { @@ -11815,8 +11781,7 @@ var error = () => { function yo_default() { return { localeError: error() }; } -//#endregion -//#region node_modules/zod/v4/locales/index.js +// node_modules/zod/v4/locales/index.js var locales_exports = /* @__PURE__ */ __exportAll({ ar: () => ar_default, az: () => az_default, @@ -11882,8 +11847,7 @@ var locales_exports = /* @__PURE__ */ __exportAll({ zhCN: () => zh_CN_default, zhTW: () => zh_TW_default }); -//#endregion -//#region node_modules/zod/v4/core/registries.js +// node_modules/zod/v4/core/registries.js var _a; var $output = /*@__PURE__*/ Symbol("ZodOutput"); var $input = /*@__PURE__*/ Symbol("ZodInput"); @@ -11931,8 +11895,7 @@ function registry() { } (_a = globalThis).__zod_globalRegistry ?? (_a.__zod_globalRegistry = registry()); var globalRegistry = globalThis.__zod_globalRegistry; -//#endregion -//#region node_modules/zod/v4/core/compile.js +// node_modules/zod/v4/core/compile.js /** @internal Sentinel the compiled fast path returns when validation fails. */ var INVALID = Symbol.for("zod.compile.invalid"); var FALLBACK_FLAG = Symbol.for("zod.compile.fallback"); @@ -12917,9 +12880,13 @@ function generateNullableCheck(doc, ctx, schema, accessor, buildsValue = true) { doc.write(`}`); return outputVar; } +function generateSizeGate(doc, schema, size) { + for (const [max, check] of sizeCaps(schema._zod.def.checks)) doc.write(`if (${size} > ${numericOperand(max, check._zod.def.check)}) return INVALID;`); +} function generateArrayCheck(doc, ctx, schema, accessor, buildsValue = true) { const def = schema._zod.def; doc.write(`if (!Array.isArray(${accessor})) return INVALID;`); + generateSizeGate(doc, schema, `${accessor}.length`); const outputVar = buildsValue ? newVar(ctx) : null; const iVar = newVar(ctx); const elemVar = newVar(ctx); @@ -13256,6 +13223,7 @@ function literalPropertyKey(ctx, key) { function generateMapCheck(doc, ctx, schema, accessor) { const def = schema._zod.def; doc.write(`if (!(${accessor} instanceof Map)) return INVALID;`); + generateSizeGate(doc, schema, `${accessor}.size`); const outputVar = newVar(ctx); const kVar = newVar(ctx); const valVar = newVar(ctx); @@ -13272,6 +13240,7 @@ function generateMapCheck(doc, ctx, schema, accessor) { function generateSetCheck(doc, ctx, schema, accessor) { const def = schema._zod.def; doc.write(`if (!(${accessor} instanceof Set)) return INVALID;`); + generateSizeGate(doc, schema, `${accessor}.size`); const outputVar = newVar(ctx); const valVar = newVar(ctx); doc.write(`const ${outputVar} = new Set();`); @@ -13410,8 +13379,7 @@ function generateTransformCheck(doc, ctx, schema, accessor) { } return accessor; } -//#endregion -//#region node_modules/zod/v4/core/api.js +// node_modules/zod/v4/core/api.js function snapshotChecks(def) { if (def.checks) def.checks = [...def.checks]; return def; @@ -14488,8 +14456,7 @@ function _stringFormat(Class, format, fnOrRegex, _params = {}) { if (fnOrRegex instanceof RegExp) def.pattern = fnOrRegex; return new Class(def); } -//#endregion -//#region node_modules/zod/v4/core/to-json-schema.js +// node_modules/zod/v4/core/to-json-schema.js function assignProps(target, ...sources) { for (const source of sources) for (const key of Reflect.ownKeys(source)) if (Object.prototype.propertyIsEnumerable.call(source, key)) assignProp(target, key, source[key]); return target; @@ -14932,8 +14899,7 @@ var createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) = extractDefs(ctx, schema); return finalize(ctx, schema); }; -//#endregion -//#region node_modules/zod/v4/core/json-schema-processors.js +// node_modules/zod/v4/core/json-schema-processors.js var narrowMin = (agg, key, value) => { if (agg[key] === void 0 || value > agg[key]) agg[key] = value; }; @@ -15578,8 +15544,7 @@ function toJSONSchema(input, params) { extractDefs(ctx, input); return finalize(ctx, input); } -//#endregion -//#region node_modules/zod/v4/core/json-schema-generator.js +// node_modules/zod/v4/core/json-schema-generator.js /** * Legacy class-based interface for JSON Schema generation. * This class wraps the new functional implementation to provide backward compatibility. @@ -15669,11 +15634,9 @@ var JSONSchemaGenerator = class { return plainResult; } }; -//#endregion -//#region node_modules/zod/v4/core/json-schema.js +// node_modules/zod/v4/core/json-schema.js var json_schema_exports = /* @__PURE__ */ __exportAll({}); -//#endregion -//#region node_modules/zod/v4/core/index.js +// node_modules/zod/v4/core/index.js var core_exports = /* @__PURE__ */ __exportAll({ $ZodAny: () => $ZodAny, $ZodArray: () => $ZodArray, @@ -15988,8 +15951,7 @@ var core_exports = /* @__PURE__ */ __exportAll({ version: () => version, withParser: () => withParser }); -//#endregion -//#region node_modules/zod/v4/classic/checks.js +// node_modules/zod/v4/classic/checks.js var checks_exports = /* @__PURE__ */ __exportAll({ endsWith: () => _endsWith, gt: () => _gt, @@ -16022,8 +15984,7 @@ var checks_exports = /* @__PURE__ */ __exportAll({ trim: () => _trim, uppercase: () => _uppercase }); -//#endregion -//#region node_modules/zod/v4/classic/errors.js +// node_modules/zod/v4/classic/errors.js var _installedErrorProtos = /* @__PURE__ */ new WeakSet([Object.prototype, Error.prototype]); function _lazyMethod(proto, key, make) { Object.defineProperty(proto, key, { @@ -16073,8 +16034,7 @@ var initializer = (inst, issues) => { }; var ZodError = /*@__PURE__*/ $constructor("ZodError", initializer); var ZodRealError = /*@__PURE__*/ $constructor("ZodError", initializer, void 0, { Parent: Error }); -//#endregion -//#region node_modules/zod/v4/classic/parse.js +// node_modules/zod/v4/classic/parse.js var parse = /* @__PURE__ */ _parse(ZodRealError); var parseAsync = /* @__PURE__ */ _parseAsync(ZodRealError); var safeParse = /* @__PURE__ */ _safeParse(ZodRealError); @@ -16087,8 +16047,7 @@ var safeEncode = /* @__PURE__ */ _safeEncode(ZodRealError); var safeDecode = /* @__PURE__ */ _safeDecode(ZodRealError); var safeEncodeAsync = /* @__PURE__ */ _safeEncodeAsync(ZodRealError); var safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync(ZodRealError); -//#endregion -//#region node_modules/zod/v4/classic/schemas.js +// node_modules/zod/v4/classic/schemas.js var schemas_exports = /* @__PURE__ */ __exportAll({ ZodAny: () => ZodAny, ZodArray: () => ZodArray, @@ -17703,8 +17662,7 @@ function preprocess(fn, schema) { out: schema }); } -//#endregion -//#region node_modules/zod/v4/classic/compat.js +// node_modules/zod/v4/classic/compat.js /** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */ var ZodIssueCode = { invalid_type: "invalid_type", @@ -17730,8 +17688,7 @@ function getErrorMap() { /** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */ var ZodFirstPartyTypeKind; ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}); -//#endregion -//#region node_modules/zod/v4/classic/iso.js +// node_modules/zod/v4/classic/iso.js var iso_exports = /* @__PURE__ */ __exportAll({ ZodISODate: () => ZodISODate, ZodISODateTime: () => ZodISODateTime, @@ -17754,8 +17711,7 @@ function time(params) { function duration(params) { return /* @__PURE__ */ _isoDuration(ZodISODuration, params); } -//#endregion -//#region node_modules/zod/v4/classic/from-json-schema.js +// node_modules/zod/v4/classic/from-json-schema.js var z = { ...schemas_exports, ...checks_exports, @@ -18324,8 +18280,7 @@ function fromJSONSchema(schema, params) { }; return convertSchema(normalized, ctx); } -//#endregion -//#region node_modules/zod/v4/core/visit.js +// node_modules/zod/v4/core/visit.js var RESOLVING = Symbol("z.visit/resolving"); function visit(schema, fnOrHandlers) { const fn = typeof fnOrHandlers === "function" ? fnOrHandlers : (node, rewritten) => { @@ -18503,8 +18458,7 @@ function visit(schema, fnOrHandlers) { } return run(schema); } -//#endregion -//#region node_modules/zod/v4/classic/deep-partial.js +// node_modules/zod/v4/classic/deep-partial.js /** Returns a copy of the schema with every nested object's properties made optional. */ function deepPartial(schema) { return visit(schema, { @@ -18515,8 +18469,7 @@ function deepPartial(schema) { } }); } -//#endregion -//#region node_modules/zod/v4/classic/in-out.js +// node_modules/zod/v4/classic/in-out.js /** Appends a pipe's own checks to the side that replaces it, mirroring how `.check()` clones. */ function withChecks(side, checks) { if (!checks?.length) return side; @@ -18546,8 +18499,7 @@ function output(schema) { prefault: (s, rewritten) => rewritten ? s._zod.def.innerType : s }); } -//#endregion -//#region node_modules/zod/v4/classic/coerce.js +// node_modules/zod/v4/classic/coerce.js var coerce_exports = /* @__PURE__ */ __exportAll({ bigint: () => bigint, boolean: () => boolean, @@ -18570,8 +18522,7 @@ function bigint(params) { function date(params) { return /* @__PURE__ */ _coercedDate(ZodDate, params); } -//#endregion -//#region node_modules/zod/v4/classic/external.js +// node_modules/zod/v4/classic/external.js var external_exports = /* @__PURE__ */ __exportAll({ $brand: () => $brand, $input: () => $input, @@ -18832,8 +18783,7 @@ var external_exports = /* @__PURE__ */ __exportAll({ xid: () => xid, xor: () => xor }); -//#endregion -//#region schemas/form-schema.mjs +// schemas/form-schema.mjs var FIELD_TYPES = [ "text", "textarea", @@ -18889,8 +18839,7 @@ var formSchema = (z) => z.object({ path: ["fields"] }); }); -//#endregion -//#region scripts/lib/form-model.mjs +// scripts/lib/form-model.mjs var parseFormSchema = (text, theme) => { if (new TextEncoder().encode(text).length > FORM_LIMITS.bytes) throw new Error("Form schema exceeds the 64 KiB limit"); let data; @@ -18957,8 +18906,7 @@ var workflowTransition = (state, event, fields, validate = validateFields) => { }; throw new Error(`Unsupported workflow transition: ${state.stage} / ${event.type}`); }; -//#endregion -//#region node_modules/parse5/dist/common/unicode.js +// node_modules/parse5/dist/common/unicode.js var UNDEFINED_CODE_POINTS = /* @__PURE__ */ new Set([ 65534, 65535, @@ -19047,8 +18995,7 @@ function isControlCodePoint(cp) { function isUndefinedCodePoint(cp) { return cp >= 64976 && cp <= 65007 || UNDEFINED_CODE_POINTS.has(cp); } -//#endregion -//#region node_modules/parse5/dist/common/error-codes.js +// node_modules/parse5/dist/common/error-codes.js var ERR; (function(ERR) { ERR["controlCharacterInInputStream"] = "control-character-in-input-stream"; @@ -19112,8 +19059,7 @@ var ERR; ERR["nestedNoscriptInHead"] = "nested-noscript-in-head"; ERR["eofInElementThatCanContainOnlyText"] = "eof-in-element-that-can-contain-only-text"; })(ERR || (ERR = {})); -//#endregion -//#region node_modules/parse5/dist/tokenizer/preprocessor.js +// node_modules/parse5/dist/tokenizer/preprocessor.js var DEFAULT_BUFFER_WATERLINE = 65536; var Preprocessor = class { constructor(handler) { @@ -19263,8 +19209,7 @@ var Preprocessor = class { this.isEol = false; } }; -//#endregion -//#region node_modules/parse5/dist/common/token.js +// node_modules/parse5/dist/common/token.js var TokenType; (function(TokenType) { TokenType[TokenType["CHARACTER"] = 0] = "CHARACTER"; @@ -19281,8 +19226,7 @@ function getTokenAttr(token, attrName) { for (let i = token.attrs.length - 1; i >= 0; i--) if (token.attrs[i].name === attrName) return token.attrs[i].value; return null; } -//#endregion -//#region node_modules/parse5/node_modules/entities/dist/decode-codepoint.js +// node_modules/parse5/node_modules/entities/dist/decode-codepoint.js /** * C1 Unicode control character reference replacements (code points 128–159). * Index i gives the replacement for code point 128+i; 0 means "no replacement". @@ -19350,8 +19294,7 @@ function replaceCodePoint(codePoint) { function replaceCodePointXML(codePoint) { return isInvalidCodePoint(codePoint) ? 65533 : codePoint; } -//#endregion -//#region node_modules/parse5/node_modules/entities/dist/internal/decode-shared.js +// node_modules/parse5/node_modules/entities/dist/internal/decode-shared.js var BASE91_INVERSE = /* #__PURE__ */ (() => { const table = /* @__PURE__ */ new Uint8Array(127); let code = 0; @@ -19493,12 +19436,10 @@ function decodeTrieDict(input, resultLength, atomCount, dict1AtomCount, ngramCou } return out; } -//#endregion -//#region node_modules/parse5/node_modules/entities/dist/generated/decode-data-html.js +// node_modules/parse5/node_modules/entities/dist/generated/decode-data-html.js /** Packed HTML decode trie data. */ var htmlDecodeTree = /* #__PURE__ */ decodeTrieDict("!}.&u%}'&}*'~!6*)%&,~!J~!J~%L~y<~!R,~~%Lu~~#GD~~#|)1#%}^%}2%+#.##%##%}&%##%'#%##&%#%#'%#&#%#&#'#%%#&#%##%#)%''%&%#%#'%#%%#%%}%%%#%#&(23#%%#&-%0%('1#(##%#'##+%'*.:1}#%#6-+(%'%%#%%%}#L'2351&('%}&/N'(0(/*-%(%%}#'+&T%7.2}#&%&#%#36/5##%&%%#&#%%#))2%%##%&&'0~!#*+&'%1~!%).'3q?&%'1~!.##%6(~!+%%%(Gw'rT~!E#%#%&}*%}(%}9%}/%})%}*%}*%}?&}&%}3%}&*#%})%#%#)}#&#-#+*%E%%'%'#%}#*V##&##I}#&&##%&%#&&Qf%%))w/0+&%#(#.%-''''++++7}>%4'',##1,#%#&%##&#'##&#*#9)%&%}#*}%,#+P(%A&%#'&##wSD',9E00#y#@}(+}&%&>~!#~!X}#*}(&&}(&}(,%}%&#+&}#&}I%#%}%)#(},'%#*}4%%#%}(''}#/##(##),%-##%%)#&}(.}&%#&}%%}*&#%},&&}&%}#%*'#%})%}D&}&%}-&}6&#&}-,%}#%})-(~+`~,=?~I9'9%~!,#%})%})%}@%}?%}(~!?~#<~#pP~#BG~#=1#%K+~#?#~%;)~#A~#mF1~#A'~'X%'~#lR~#N~'N~#r~#m#-~#i'?%#'%~#B%##%,%#~#_%#0%~#]732~,w~2+#:&#%&'0%&>%}#>##F+)#%&&#(+_}4&}-%}(&}@&}O7Fdf0@+/v4}&WU##&/0#&'('B#%}.%}'+#%}#%%&#&%#%##+#&#)#6#'#.},%}c%},%#%##%&#&%#&~#>'*-.%##%##%}#%%}%'~#)D1}#%*&~#_%%'(~#S2%'.}#~#=##*'*-%}&'%'##&&~'E%.#&~#M4}%%##&'%#~#O1##%&#'+~#~#UA%-%##&~!C%~!-.9:~!1~!-^2/:a~!y,D*J#-5)/4~%23,~#G~!L1~!0X3`~!2+~!!0-~&E~!W~!o,>Y&]~%cZx_&~#O*9#A#'#+I'%#)~!0B*-5A+-((F&*M#)(-7-5+'-3a5Vi~!Y~!?+[)%3),ERHm~!+:D,VG.+)?fB%%*(%)'(#&80%1'8`K8?`+'Z#&O&'H5#*9)A%%5&3))0%39+.*7#()&&*=4@**L)<'_&*+..;(#*+)./&0#3)%')-8(4ixD(&.}%,('aI:,)%,k2231T)I'#/-W7,/'Q#.'Y24+h')37w+vu9i[~>g5uI~=RvdwEg;v/g;uk!!TTSx]@RT!U!#!@VBRUU!'UTe-d0c`e&gSdicedFcrdTaqb.kYcAohdYd@a3e+d}dMdtd.aJ#bqcK`dle/e.e'dwdPdodddjbEb}ogd^ofdpduc6j?l%d{drdqc)d7bacOdQ%T#Y)X.sR[yH>6Vyv3[xwLu>vo'!*.[yBacahoj>6Rew3[xqdZa#!a&#^(X-[yG>6Vyu3[xvg3sEr|g.u/Ri9db0T#^(Xa)!-[y;>6Vylg4wKs{JwNZt3@3r=c4Z([xlg;wKt!cpq's@v7A'*a(a+!-a#[y<3Dt?3Dt'>6Vym3[xmg9rxsNJwLZt4~?r?db1T#`-!(Xa,!0[yS>6Vz%NuQs.g4wKtnJwNZtS@3r>c4Z([y%g;wKtrdga8!a(!#&T*Y-Xa#!a06Vz43[y3JwNZtf@3s!Ju}!%Dti:pm3c_%X#tjB5pkd6q!r]u?voC'*-a.a2!0a&a+[yI3DtI3Ds~3DtH>6Vyw3[xx;:s#~<5pKJwNZtE@3r~d`a)!a2T#a.(!+U.X1[yT3Dt`3Dtv>6Vz&3[y&g9rxwzcxstPu.6Vz23[y1g3sEr}wkg{NuQRg{ci(U#5@b`~,cg#U(2WnH5wugcRh7dX#T(Y,a'Ta!!a,[yZ<]mj>6Vz,3[y+Pv#5ReZKu+=,%!H}7ABwkaS?Rh:BcW(X#<]mrj:ubv/ARekdg%!(!a.*Ta(Y.X1!#sP>Rl*Dt6[y>>6Vyo3Wf*jOvuumvuRgRJuq*!:96Re}3[xy~<5s%JwJZt1~Gs)c;&!#2sJkNuXvzq7rxu,Re8dka4!a8(aEZ+a@Y.X1Xa)[yd=Bs(3DtP>6Vz53[y4cX#X&Re:avRe9~<5s&JwJZtQ~Gs*i^rzvdRg+Jv{%!2sbB@bX}kdga,!Za?&^*T1/!a'Dt+[y6>6Vyf3Wf%g/u;s4hGu6?Rh-JvZ,!c%#&RoX54Rivj7uyvf8RgTKvZB%*!2sGh[y93Wf)coZ(T,6VyifluvRgC@95@B@bX~/hFu34cC#T,k/unq8w8Q5RkUklwQuzunq8w8Q5Rk8d/rJu?v8w9)-&!a0a;a&aIWejg3sEr/h1s23E~5c:Z&bX};kKv?w&unuVu5Rjc;>bs)#~@:Rh.=ay6Vyt3[xuNuPRi&NuPwpi#RoWh?vf8Ri%Jv]!%Ri:KvxD!.'2WeAjZu`q9rxu,Re7woeAg-unLq(qA_/*2Wg_g3u5q^9:4E}/jTrxrzv=Wkkd~0UX#^^Xa-a1a5T&a=U1a'*aEa]!a*aPaA-adok[y54Rn>;:p3~Dp5g9rpsFNvZqjg3uJp4~<5p0Pw;5qlJwNZt*@3p1Pw:5p/Ou!5p2JvG'!6Vye=Rl!9ARiq5E}Qg=ucRkBE|oJrJ_@Wk~@Wk{JrJ_@Wk|@WkyJrJ_@Wk}@WkzJvO_[y2g-vMRmiKuYC!)&>Ri;>Ri<@3RkNc](X#@9Rk=g5vuRmhKvDB!+'=]meg3u4Rmgd)#Y'Vz3CARmfd`a+!%T'!+#Ta1Ta6TaM-sTDt9[yA9sYd'%Y#s[[xpj:ueunaXRgEjRq,v-vuqdd2'`#6Rev<32@5>:2vyRgNj8w)v86Vyj3[xkg6ruwjcqsrPw;5r*Ku]D'Zt-@3r(~?r.i[vwv]dU1a--U#`a4(g/vsRhPOu!5RhLj:rmu9Wo!~@:wdh@g/vsRiTjXuvvNr}:RhBj^v(pyw8unRn]dz1UYa'a+^Y(!aETZalaRY.Ta?a4[yDJw1!#qLsW>6Vyrfzq-pLflpwRe|Js>%!Dt@3Dt&Jvy_[xs~HrnjMuwpsw'RecKu+D#'!t<~Grl~?rjg5u-x,gwp{ah!-(~@:Rg~Ou!5Rh'jXuvvNr}:Rh#cW#X/c;&!#2sLi[v7u7RgpJv)(!iLrxu,Re6j7v@s@5Se[e7d`aW!Za(a`T.a#!a3!&aDa-!9)Dt_=6s+3[x~~DR|h~DS6avhGun5RkZj3w)v-]mkKunB!&*]kb97R|icQ#%T'p-Rf8Rf=ct#%'(*!,p,Rf4p+Rf6Rf:Rf3Ds}KvGB)_6Vyk2sM=6Vyp;:pE~DrY~<5pBJwNZt8@3pCh=rt3rWPw:5pAJup_[xoNuPpF9c!#'45pD5ARn)d8#X'X*3@rU72s]h>v<RoUWeL>:Cbb|?JwPZtVg6ruRmzJvD'!6Vz(g/vmRh~Jvy_[y(g9voRgyx*cy(#2>Ri2B9b]~9kIw9u7rluJu3Rg]dI#a%UY'@=p%CAx.gQZ&RhwwygtRm{x5g_Z'+ABqR9Woa=Bp&dV#^*Xa'!&@o{g4v]Rk;Jv{!%Rk[wkkiA5RkiwwfUB=x,fUuqC&*!>RfTg8v0RfV~ARfSd;rJsAuAv9wR'ae+/aO!a@aza/a#[yQ@Wg!2Wemg3sEr0JvB_g>uvReWg2v+Re=KupB_+[y!2AbY~-~Hr2AJwD!(h<~El>h<~El?Kun@+_:9b`}Kg-v/Ri3g;vtwyk_9]k_d=&T#*U.6qh@Ab`|K9:H|CJv[!&3Dtex'fDwC%!Rf[9WlMd[(^X,!a%Z06Vz!@WgBg=v~Rgvg,QRe@awd,#Y+jTv|Q~EfWj]uNr|~FRfXdy#Y&^Ua%!aO.!(a)Ua;=!a@aKap!a-,a!Ta]a[rSa]p?[y82sK=Bq~;:p:~<5p8Pw:5p7d'#Y'Wf(;RnRi[u4w&RgJJvG'!6Vyh=)!&6Ri154s,KuGB_%@r68r:dJ|t`#X(9b6a3b%!/aKa/)!arwve^VyJ;:pR~DpTg3uJpS~<5pOPw;5qmPw:5pNOu!5pQJvG'!6Vyx=wkh'?Rh,x8gyt`w5D!&),(SgyccRgztJ@3pPB5p#d'(Y#<]mmifubw&RgoJvE&!82s^JvF&!8Rf,ADb]~;x=h'rNu]vK!,%'*0RnORh)4Rh*AqQg-vaRnNg;wHwkh'ba~4cE#Ta*x3gctyw@'!+%RnFRnD<4Rn@hFvK5RnCxWg[#`&a0Ua()`1Rm75Rg[c]%X#qi8Rg^NvdRj>BwzgZauwji7Rm6A4wgg]d1#&(*,.0a#Rm;RmRm?Rm@RmARmBe%#^^^Xaea?aC/b+(,!a+a#!a/!>a&Ta6Vy~g6urRf.x,hPrNav!%'RnqRo%Ro#Nu;q[Pw;5r+JwNZtM@3r)d'#Y'Weh;xChL#`&RnmRnoKu}>%(!Rne~Bs-;2wjcussJv+'!aYSO}6@B<5?ba~8LrNvj!.%*ROwungw~ng~:9;Ri^>wtnig;wHRnixDh@|(UZ.x1h@|)!#:2@=be}]?cl{{U#:5Abb}Jds#^YaF!a*b4a#a3aPa>&Tb!bH!*a_!Eau?/a&RjY<]gj>6Vz*;:pe~DrZg,QRj1JwNZtX@wihspcJvZ&!VyX9WmOJu|!|N2WmHJvh&!]ht~Bpbcn&T(!#RmQRmKCARhnKup=!)&Wf+:RhqNuPpf9c!#'45pd5AwghpARn(Ls@w!%,)!RmP@Wfe.a6!a:aO`aJDtL[y`@Wg#>6Vz12@wzoYRoZNuPRi!NuPRhzg=ucRi,@=b`{Yg=ucRi-ACJvB!&Sh[ebSh]ebi`wUuFRm4Jw2_[y0JvB!.>bU{0j9udv:Bb_{TJv`!&g/r|snj6v(us5d,#Y(56H}[978H}]Jw5!&g1rushJvB!+j;v{u5?zDhd}6}bj;v{u5?zDhe}6}ce*#`(^^^a[aea!=!a6a*aoXb1a.!aAbL!b>,b'aL!aV@Wf|2Wlg3[y/JwNZt^@3piPw:5pgJunZou3@rsJva&!Vy_gg5u-rqJvy'!@9RkQcH(T#=>Ri~@Ri}@2@@=aybb}XjWv0Q~EfEj3vLv;5@d##Y+jTv|vV~EfFj]uNpn~FRfGdgaK!Z2&!a8a-Tb({E!acTbM*!a(DtY[yYd'%Y#sl[y*hHvh>Re5x2c{Z}.j4uCvcawRiMd+#X+_x&d!},<5RkX;2Hzw@x,gavfB-!{CcF&T#Roe;RodwWbBg5urRgaKvHC*_6Vz+<4opieuew&Rmq@d]&Y)X,T#X0Rh}Ro5CE{A9b]{@;5x#eO{:g;urRi+KrNA!%(Ro3>Ro79;Ri_Ku@>{;&!x%gX|{KunA_+g5QRj/g3u5Rj#g>uERj%wio/xRhS&!,!#^1U}wba{8>>@=be}qC@:D5ba{7Ku+A&!}x?ba}t>>@=be}se(aA^^^Uat!b0#{pa+awUazbGa#aLb9bgaWac'a5TbS=Br!d1#`%scp_Jvl!#rT>Re0JvX&!VyN=H{Fcm#U&:pY=ReaJv2&!]h0=]nUJvG'!6Vy|=!|l=w^e1bp#&Re2Re3BDx7gH#T|f5H|eKuZ>!%(:qNAH{]Jv6!+3B2B9=b^{X<5x]z/@awRoTd+#Y(az]hFhCrm4d,#Y+jTv|Q~EfMj]uNr|~FRfOdCa!Xa9_X#@>@=be{#KuY>!+&4Ezyi[ugv&RjIdea+T)#UXa&T-T&a!Rh9auRmW=]kLg5vuRn+g3u4Rn-Ow6ARn,hHus5xNk?#UX(U~)/g8v0RkD~AwkkF?Ri.OuNBwkkA?Ri/d|a2`a*^UYa.!aBTZaTa'Xa;!(!2!-a#b2[yC>6Vyq3[xr2Wi?g1rusVh%s?DtF~<5rbJs;%!DtBfswKtCj[uvuSsEu3RgVx3o:u+wN'*Zt;@3rd~Grh~?rfg8w)Lq)qE&-a%!>bI|`jWv0vV~EfCjTv|vV~Ef@j]uNpn~FRfBcK#T']gWNu7x,k7q4ai(0!hHv8waiL2b`{QJv*_Ouv2qgjZa&!*UaA=2Wls3cH#T(@Ri|b~'#23s9h<~El.d'#Y&Dtxi^rzvdRl#d*#U%(o|B2s`hJwSaxRmDKv4B&!1:Rmdd5#`'Vx}to~Hq{x'f1v3(!BA5ba|bJv_&!Wfug1v]ReIdO+U/Y#&G}-8wze=Rh{g1v]ReHg/uQRf/by#)ibQwERl/cH#T(@Ri{cNu+vlax-!(#a0qa9aY?C9:9au@9Cb]}9cl#U*5;5KqRlR=c>Z,k#u3vWs@u2]krvgwyk^9]k^Jv3_@WfbAARkhJw2_[x|JvB_wkoIRoKwkoJRoLd'(Y#<]gm=<9Awwn;;Rn=c:Z'ARn<=Rn8Jw0!&>Rn:>Rn6cY#a7+!a&=978H{Dd_#{2^Y%_+qbbb{6g3sERhsbU{?dfa.,`a(XaRn7Jw0!&>Rn5>Rn9Lunw?&a2!,5ReGJwPZtK<7Rh+h<~El,Pv#5ReR@awwxjCg,ulRjDJv6&!]j!z?aQeeg>w=Shx'h-u(!%Ro.w~h.zPdNZ(X,Ya![x{;9ReY;wkgxRiF:x?ap#Y&RmUgA9:=b^}zKuh=a''!3awRk3c*'!#aHRk6c+Z&Rk5Rk4Jv)&!awRjSawd9*`#0?C2@EzMj8uuq@_+=ayb^|W~ARkEOuN]k@7dhzV^X/X&a-#zRzSb`zXcJzTT#2WkVKvDBzW!%FzY9;5bbzWjQrquJu3Jw3%!b`zU=ayb^zQd:#X(T-a!6Vyywxh}=b]{Jg=u1RiAdGp~qHtzv!w(wA+a+a;!,')~<5qeGzq9F{W=c##%s5au:5aU3CBE|;d4#X(D!a&6Vygx(b;#(=]ed?C2F{NaU@@=I|1OuNBc1Z+jTqIsBv=Wlc~Cw`fl2WlZ~AcTa%!Z+jTqIsBv=Wlb~Cw`fh2WlYk+uNqJsBv=WlSg,u3dca3#UXaMYa)TaB-=cM|7T#cB{/T#=ayaL.bo6!a#CbTa'T#Re{2Wlh2@G{yg6t~Ro_NvdRfticuRQRllJv3&!x&c|zs@Jw3!%RflwpfkRlpKuL;%(!Re<@G|C2GzdhIvuBwgjAg-u0RjAKQB%!(GzZ@G|5NuuRl7d='T+Y#Vy[gJvA!)@wma=]m1ifuaw&RmnLs@vT'!|/+[y,g:v>ReTJw1!#qX=x!eC{bLu+wT&)ZtZauq_~Graci&U#F|89:r_Lupvq!.)&2RlG8RfaC=x!eF{_h?rpWlmd&'!#X|&]k::xJey#`'T|+RlyARl9b[z[>RfZ:RlL:RfRwlg/ARl;9;RlxKv,A/!%7s69<74=BA5ba{-8Bde#`aRfk=ayb^}4~Ad1#`*@@=aybb{w2@>==KqRlT=c>Z,k#u3vWs@u2]kqReD2@G{42@G{5~DpM~<5rc=Bx6i>{RT#RnI@zCx]y]z:2Jv[!zr5Awyk]9]k]dD(Y+X#6Vz.g=wKtgwhaCwgmTWj2Lu,w%_+/[y-B;b^xeg3u3Rj-2@bX{*KrJRkdJwMZtc3Dtd@BcG#T'9bWxg2@2Fznd*#Y+;2x'c}wRn%:A5B;bZ~%KvhCa!a2!x>k7#Uxb@b{#xaRk7Jw0!)>wwhlShl}6>wwhmShm}6CJvB!.x'hhvj{!!5Bwkhhbaz}x'hivjz~!5Bwkhibaz|xEhTrNu,v-vpD!a%&/)a3a.,%Ro2t[CE{)@3re9b]{%wjo09:rgc:Z&Ro6=Ro89;Ri`dSaL'UYzxZb)7Rka3xRhT&!,!#^1U}vbaz{>>@=be}yC@:D5bazzKu+A&!}{?ba}y>>@=be}wxBh[t`u~vJvr!%a!a()a,a0a4RoC=]o;Ju(!%RoGRhdwjh`=]oAg>w#Ro?g5vuRo=NvdRl|Ku]C.!&;RoEJvB!%RoORoMBx'h[v+_?w~h`}~5?w~hd~!xKh]oiptu-utv.vp!#%&a30a@a'a+(a/aOp(o~p!RoDJu(!%RoHRhewjha=]oBNvdRl}g>w#Ro@g5vuRo>c[#X']ox7gL#TzuwjirRipcon;>z=h-MSh.Mwqczx'a7vj&!>Re4@=ResJt__NuPRi*NuPRi)j]uNr|~FRfzKrJ>_+@Wfy@Wf]2WocKrJRn1~?rOc:Z&Rn2=w=Rh=g3w*wwgGRgGcW(X#;Sg}M2Gzk@Jv`!&awRl=wsfGIz`dKZ*T'Y-:RhR7RhQg5u-p`j6v(us5d,#Y+~Awkia?RicOuNBwkibba}Ld6p~tyu_vbAa'a+!a/'a3aEa8a!>Sh,ebJv{!&Sh@ebSaReb9;SgwebNuPRi(NvdRl)NuPRi'hHu^(!a.3wkhZba~(x,h^u(A!&(SoCMRhb5Bz=h[eb?w~hb~6x,h_u(A!&(SoDMRhc5Bz=h]eb?w~hc~6e)aA1T#T,^^^c-bMb&blcPaP(a/!0!bA=b5c@a(!bfbrc#2afwmhARnjwchORnp2Wlf3DtsNvdRl-2@wpa<]m0bx(#:awRk2@Jw3!%RfhwpfgRlnKQB%!(G{V@G|'NuuRl6d='T+Y#VyUgw*wgj@g-u0Rj@Lu+wT&)ZtUauq]~GrGci&U#F|39:rELrNvj!.%*RhCwunfw~nf~:9;Ri]>wtnhg;wHRnhx3hDs@v~!/+'@Wfr@9RkSNu&Rlo=@<5GzoKs0@_+@Wl+@awRkmJuh!-3d(}pY#qWJvj!%Rm(:Jw3!%Rm,Rm*de&!1U-U#`)Re;@G|.@9Ri82@wjfvRlq=@<5GzpLvOvr!).&2RlF8Rf`C=x!eE{.Jw3_g2QRlkhLrpWlPde(!#U{s,UXa*Ta'[y'g:v>ReS;x0PZ&RnlRnn~HrKJw1}f!=x!eB|2w]aP(#Xa&a*Ta.Ua2a7=]iOd'#Y&Ro&WnWg;u.RiDg6vjRiBNvdRlzhNvj]nYJuW_2Wm3x)kFze{9d])!a.!,Y01!#&aC!a3RndC=ox~BrC@2b^{pg,rlse7x'ksuq!%Rm.E{xidw(wBRmGx9o+)X#wwo-So-}69:Rl4@xSf@a#XZ'X)X,Ta(/ARl8b[xc>RfY:RlI:RfQwlg.ARl:9;Rlwdn'#^XafaQa1X1TaHTa)@b[{zcZ#X'7RkwWg@Ou4ARn&x)kG#{,g7u/RkGdH'U#Y*Vz'Wm&CARm|bx#(A]gUbUzJj9Q~=d,#Y(56H}l978H{U7d,0#U*2>ABb_xZ978BbU{e~AJQ{g!978BbU{hxMh?ad{oUYZ.x1h?{l!#:2>@=be}F?JvS!&BG{d7BG}(Bde#`a1X,Ya@!a'P~=wxf@2bZ}I56B2@@=aybb}08@55B9;5bb}Rfg=ayb^}&OuNBKuLA!)a!P~=x#fD{f2@>==23ExY5@Dah89b^~689Jv)!~2b[~1Lv'w(%*!a#bX|aPrmawRe]keu7uhv-q6rxu,q`xTo]/a5aU!bNaDXbi!b-!ao!bRhG<7@C5vIbs)#?C2F|9jPv0w.vISh-MKvUaz(.!9ABbb|[5;5unwfh;9:4E|YjQsBt|vjx'hYq3!(?C2F|J:2kJv~vYrquJu3x4ib#T)2@SmZM?C2F|Bj:rmu9@xPhI(a*a#U#`a3-5Abb|L~@:RhK9:4E|0@52B5G|#C::aY?C2F|-:2!a)-g entry.type === EntryType.Element && entry.element === element); } }; -//#endregion -//#region node_modules/parse5/dist/tree-adapters/default.js +// node_modules/parse5/dist/tree-adapters/default.js var defaultTreeAdapter = { createDocument() { return { @@ -23147,8 +23081,7 @@ var defaultTreeAdapter = { }; } }; -//#endregion -//#region node_modules/parse5/dist/common/doctype.js +// node_modules/parse5/dist/common/doctype.js var VALID_DOCTYPE_NAME = "html"; var VALID_SYSTEM_ID = "about:legacy-compat"; var QUIRKS_MODE_SYSTEM_ID = "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"; @@ -23246,8 +23179,7 @@ function getDocumentMode(token) { } return DOCUMENT_MODE.NO_QUIRKS; } -//#endregion -//#region node_modules/parse5/dist/common/foreign-content.js +// node_modules/parse5/dist/common/foreign-content.js var MIME_TYPES = { TEXT_HTML: "text/html", APPLICATION_XML: "application/xhtml+xml" @@ -23503,8 +23435,7 @@ function isHtmlIntegrationPoint(tn, ns, attrs) { function isIntegrationPoint(tn, ns, attrs, foreignNS) { return (!foreignNS || foreignNS === NS.HTML) && isHtmlIntegrationPoint(tn, ns, attrs) || (!foreignNS || foreignNS === NS.MATHML) && isMathMLTextIntegrationPoint(tn, ns); } -//#endregion -//#region node_modules/parse5/dist/parser/index.js +// node_modules/parse5/dist/parser/index.js var HIDDEN_INPUT_TYPE = "hidden"; var AA_OUTER_LOOP_ITER = 8; var AA_INNER_LOOP_ITER = 3; @@ -25980,8 +25911,7 @@ function endTagInForeignContent(p, token) { } } } -//#endregion -//#region node_modules/parse5/node_modules/entities/dist/escape.js +// node_modules/parse5/node_modules/entities/dist/escape.js /** * Get the named reference for an XML special character or U+00A0. * @param char Code unit matched by one of the escape regexes. @@ -26028,8 +25958,7 @@ var textEscapeRegex = /[&<>\u{A0}]/gu; function escapeText(data) { return escapeWithRegex(textEscapeRegex, data); } -//#endregion -//#region node_modules/parse5/dist/serializer/index.js +// node_modules/parse5/dist/serializer/index.js var VOID_ELEMENTS = /* @__PURE__ */ new Set([ TAG_NAMES.AREA, TAG_NAMES.BASE, @@ -26140,8 +26069,7 @@ function serializeCommentNode(node, { treeAdapter }) { function serializeDocumentTypeNode(node, { treeAdapter }) { return ``; } -//#endregion -//#region node_modules/parse5/dist/index.js +// node_modules/parse5/dist/index.js function parseFragment(fragmentContext, html, options) { if (typeof fragmentContext === "string") { options = html; @@ -26152,8 +26080,7 @@ function parseFragment(fragmentContext, html, options) { parser.tokenizer.write(html, true); return parser.getFragment(); } -//#endregion -//#region scripts/lib/anchors.mjs +// scripts/lib/anchors.mjs var anchorFor = { verification: (id) => `v-${id}`, component: (id) => `c-${id}`, @@ -26178,8 +26105,7 @@ var anchorFor = { nonExample: (id) => `x-${id}`, fixture: (id) => `fx-${id.toLowerCase()}` }; -//#endregion -//#region scripts/lib/form-fields.mjs +// scripts/lib/form-fields.mjs var FIELD_COMPONENTS = { text: "text-field", textarea: "textarea", @@ -26311,8 +26237,7 @@ var readFieldValues = (root, fields, prefix) => Object.fromEntries(fields.map((f const value = field.type === "checkbox" ? input.checked : field.type === "radio" ? root.querySelector(`[name="${fieldControlId(prefix, field)}"]:checked`)?.value ?? "" : input.value; return [field.id, value]; })); -//#endregion -//#region packages/ui/src/internal/form-workflow.js +// packages/ui/src/internal/form-workflow.js var mountWorkflow = (root, { fields, templates, prefix, validate, signal }) => { const controller = new AbortController(); signal?.addEventListener("abort", () => controller.abort(), { once: true }); @@ -26425,5 +26350,4 @@ var mountWorkflow = (root, { fields, templates, prefix, validate, signal }) => { destroy: () => controller.abort() }; }; -//#endregion export { FORM_LIMITS as a, FIELD_TYPES as i, emptyValues as n, parseFormSchema as r, mountWorkflow as t }; diff --git a/packages/ui/dist/copy/settings-panel/runtime/chunks/forms-CE_hP1hg.js b/packages/ui/dist/chunks/forms-C3u5121t.js similarity index 96% rename from packages/ui/dist/copy/settings-panel/runtime/chunks/forms-CE_hP1hg.js rename to packages/ui/dist/chunks/forms-C3u5121t.js index 6ad3b48f5..7eaab7c98 100644 --- a/packages/ui/dist/copy/settings-panel/runtime/chunks/forms-CE_hP1hg.js +++ b/packages/ui/dist/chunks/forms-C3u5121t.js @@ -1,5 +1,5 @@ -import { i as all, l as make, o as enabled } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/forms.js +import { i as all, l as make, o as enabled } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/forms.js function wizard(root, { on }) { const panels = all(root, ".wizard-panel"), steps = all(root, ".wizard-step-button"), backButton = root.querySelector(".wizard-back"), nextButton = root.querySelector(".wizard-next"); if (!panels.length || panels.length !== steps.length) throw new Error("A wizard requires one complete panel for each step button"); @@ -119,5 +119,4 @@ function formComposition(root, { on }) { if (root.querySelector("[data-start=\"review\"]")) showReview(false); return {}; } -//#endregion export { wizard as n, formComposition as t }; diff --git a/packages/ui/dist/copy/form-builder/runtime/chunks/markup-DeQ4bEMR.js b/packages/ui/dist/chunks/markup-AopKpwOF.js similarity index 97% rename from packages/ui/dist/copy/form-builder/runtime/chunks/markup-DeQ4bEMR.js rename to packages/ui/dist/chunks/markup-AopKpwOF.js index 77bd9471d..bc1c52c0b 100644 --- a/packages/ui/dist/copy/form-builder/runtime/chunks/markup-DeQ4bEMR.js +++ b/packages/ui/dist/chunks/markup-AopKpwOF.js @@ -1,4 +1,4 @@ -//#region scripts/lib/markup.mjs +// scripts/lib/markup.mjs var IDREFS = /* @__PURE__ */ new Set([ "for", "form", @@ -50,5 +50,4 @@ var namespaceMarkup = (tree, decorate, { strict = true, renameNames = false } = else if (renameNames && attr.name === "name") attr.value = decorate(attr.value); }); }; -//#endregion export { setAttribute as a, removeAttribute as i, hasClass as n, walkMarkup as o, namespaceMarkup as r, IDREFS as t }; diff --git a/packages/ui/dist/copy/badge/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/chunks/native-D61761VL.js similarity index 98% rename from packages/ui/dist/copy/badge/runtime/chunks/native-BjBt1sUh.js rename to packages/ui/dist/chunks/native-D61761VL.js index 032f76c74..d73311256 100644 --- a/packages/ui/dist/copy/badge/runtime/chunks/native-BjBt1sUh.js +++ b/packages/ui/dist/chunks/native-D61761VL.js @@ -1,5 +1,5 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js function content() { return {}; } @@ -285,5 +285,4 @@ function fileInput(root, { on, signal }) { attributeChanged: draw }; } -//#endregion export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/navigation-BfNzDYZB.js b/packages/ui/dist/chunks/navigation-CknoksQ5.js similarity index 99% rename from packages/ui/dist/copy/compact-dashboard/runtime/chunks/navigation-BfNzDYZB.js rename to packages/ui/dist/chunks/navigation-CknoksQ5.js index db2779553..dfd1883e6 100644 --- a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/navigation-BfNzDYZB.js +++ b/packages/ui/dist/chunks/navigation-CknoksQ5.js @@ -1,5 +1,5 @@ -import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/navigation.js +import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/navigation.js function tabs(root, { on }, listOverride) { const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); if (!list) return {}; @@ -373,5 +373,4 @@ function menu(root, { on }) { } }; } -//#endregion export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/chip/runtime/chunks/overlays-BwgpF4jI.js b/packages/ui/dist/chunks/overlays-BW66WXLm.js similarity index 98% rename from packages/ui/dist/copy/chip/runtime/chunks/overlays-BwgpF4jI.js rename to packages/ui/dist/chunks/overlays-BW66WXLm.js index 4b8de2e8b..d05c73b46 100644 --- a/packages/ui/dist/copy/chip/runtime/chunks/overlays-BwgpF4jI.js +++ b/packages/ui/dist/chunks/overlays-BW66WXLm.js @@ -1,5 +1,5 @@ -import { d as place, i as all, o as enabled, s as identify } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/overlays.js +import { d as place, i as all, o as enabled, s as identify } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/overlays.js function modal(root, { on }) { const dialog = root.querySelector("dialog"); if (!dialog) return {}; @@ -241,5 +241,4 @@ function feedback(root, { on }) { dismiss(id ? root.querySelector(`#${CSS.escape(id)}`) : root.querySelector(".toast,.alert") ?? root); } }; } -//#endregion export { tooltip as i, modal as n, popover as r, feedback as t }; diff --git a/packages/ui/dist/copy/data-table/runtime/chunks/tables-Cjr1EIJz.js b/packages/ui/dist/chunks/tables-zo8ebTOo.js similarity index 98% rename from packages/ui/dist/copy/data-table/runtime/chunks/tables-Cjr1EIJz.js rename to packages/ui/dist/chunks/tables-zo8ebTOo.js index f82aaf25e..56f7f3dc3 100644 --- a/packages/ui/dist/copy/data-table/runtime/chunks/tables-Cjr1EIJz.js +++ b/packages/ui/dist/chunks/tables-zo8ebTOo.js @@ -1,5 +1,5 @@ -import { c as keyIndex, f as rove, i as all, o as enabled, s as identify } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/tables.js +import { c as keyIndex, f as rove, i as all, o as enabled, s as identify } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/tables.js function table(root, { on }) { const element = root.querySelector("table"), body = element?.tBodies[0]; if (!element || !body) return {}; @@ -213,5 +213,4 @@ function pagination(root, { on }) { } }; } -//#endregion export { table as n, pagination as t }; diff --git a/packages/ui/dist/components/admin-form.js b/packages/ui/dist/components/admin-form.js index f786258d5..76c220293 100644 --- a/packages/ui/dist/components/admin-form.js +++ b/packages/ui/dist/components/admin-form.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as formComposition } from "../chunks/forms-CE_hP1hg.js"; -//#region .cache/ui-build/entries/components/admin-form.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as formComposition } from "../chunks/forms-C3u5121t.js"; +// .cache/ui-build/entries/components/admin-form.js var J3w1AdminForm = class extends J3w1Element { static componentId = "admin-form"; static version = "4.0.0"; - static implementationId = "sha256-86V5kk3lZt3iA5GdiMBYc8P2mc4pO3KTo02FmkKh71k="; + static implementationId = "sha256-nRr2ehiaHW5Pojp+99nPTbxKA38KgfMFXwRXtoTEy/U="; static connect = formComposition; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1AdminForm }; diff --git a/packages/ui/dist/components/alert.js b/packages/ui/dist/components/alert.js index c434333d3..2d9691c78 100644 --- a/packages/ui/dist/components/alert.js +++ b/packages/ui/dist/components/alert.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as feedback } from "../chunks/overlays-BwgpF4jI.js"; -//#region .cache/ui-build/entries/components/alert.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as feedback } from "../chunks/overlays-BW66WXLm.js"; +// .cache/ui-build/entries/components/alert.js var J3w1Alert = class extends J3w1Element { static componentId = "alert"; static version = "4.0.0"; - static implementationId = "sha256-UxXRTp+Yf7lbD/vkY8rJ0A/kKL5Xkg9lnOEAvWcr7OA="; + static implementationId = "sha256-/VGmtLvULiNusvurQPJTqOcanOEqt+p9HsSZ3hi9Nyc="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -13,5 +13,4 @@ var J3w1Alert = class extends J3w1Element { return this._api.dismiss(...args); } }; -//#endregion export { J3w1Alert }; diff --git a/packages/ui/dist/components/avatar.js b/packages/ui/dist/components/avatar.js index 39f8bb7e4..f7e439c41 100644 --- a/packages/ui/dist/components/avatar.js +++ b/packages/ui/dist/components/avatar.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as avatar } from "../chunks/display-Jm9bAsnb.js"; -//#region .cache/ui-build/entries/components/avatar.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as avatar } from "../chunks/display-l54fb8vw.js"; +// .cache/ui-build/entries/components/avatar.js var J3w1Avatar = class extends J3w1Element { static componentId = "avatar"; static version = "4.0.0"; - static implementationId = "sha256-y5w6c1MQTafVvxzhJ5TzYxwGvju264CUxS2D23RvGCQ="; + static implementationId = "sha256-h7ZI0GBRPh8k+G66StFqOp3ztZR+AceNt5+PiDohQ+M="; static connect = avatar; static upgradeProperties = [ "disabled", @@ -28,5 +28,4 @@ var J3w1Avatar = class extends J3w1Element { }); } }; -//#endregion export { J3w1Avatar }; diff --git a/packages/ui/dist/components/badge.js b/packages/ui/dist/components/badge.js index 640dfde53..1f3ff68a1 100644 --- a/packages/ui/dist/components/badge.js +++ b/packages/ui/dist/components/badge.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/badge.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/badge.js var J3w1Badge = class extends J3w1Element { static componentId = "badge"; static version = "4.0.0"; - static implementationId = "sha256-4j+faVdrUDtcCc6a5/1Y+y9U30DXfpq/Frm/Z0bO1i8="; + static implementationId = "sha256-UhaZtelaZOVA7hb0+yXsIb0PG9ooJXYf9c759KHeA9c="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Badge }; diff --git a/packages/ui/dist/components/breadcrumbs.js b/packages/ui/dist/components/breadcrumbs.js index 5ce93d88b..f90b820a6 100644 --- a/packages/ui/dist/components/breadcrumbs.js +++ b/packages/ui/dist/components/breadcrumbs.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as disclosure } from "../chunks/navigation-BfNzDYZB.js"; -//#region .cache/ui-build/entries/components/breadcrumbs.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as disclosure } from "../chunks/navigation-CknoksQ5.js"; +// .cache/ui-build/entries/components/breadcrumbs.js var J3w1Breadcrumbs = class extends J3w1Element { static componentId = "breadcrumbs"; static version = "4.0.0"; - static implementationId = "sha256-9uiBLPIbEVI200s39xDO7x0K09v+wPg5xcoMI5B5TbY="; + static implementationId = "sha256-UzuPAevxgWxvLwLS5TgOGWH3gWcdZo9B3pvbMu/55Yc="; static connect = disclosure; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Breadcrumbs }; diff --git a/packages/ui/dist/components/button-group.js b/packages/ui/dist/components/button-group.js index e5443b0f9..bf93a804c 100644 --- a/packages/ui/dist/components/button-group.js +++ b/packages/ui/dist/components/button-group.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as actions } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/button-group.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as actions } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/button-group.js var J3w1ButtonGroup = class extends J3w1Element { static componentId = "button-group"; static version = "4.0.0"; - static implementationId = "sha256-QC6YHzPpUytpyeDknjyX9Ke/akglG1NzBtJnCYjqgaA="; + static implementationId = "sha256-nnr9B7SyHVj5bc9rHfUyedaHq9k8ZhIaf8pJalBfpeU="; static connect = actions; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...[ @@ -13,5 +13,4 @@ var J3w1ButtonGroup = class extends J3w1Element { "tone" ]]; }; -//#endregion export { J3w1ButtonGroup }; diff --git a/packages/ui/dist/components/button.js b/packages/ui/dist/components/button.js index 3dfd4d373..fb03b5228 100644 --- a/packages/ui/dist/components/button.js +++ b/packages/ui/dist/components/button.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as actions } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/button.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as actions } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/button.js var J3w1Button = class extends J3w1Element { static componentId = "button"; static version = "4.0.0"; - static implementationId = "sha256-5XqIG0jRl2EIptqWgZIiuSKdNf0pHpMOZB14A1W3DqU="; + static implementationId = "sha256-koXqbIz5v3u05mvNMvJSSn5/vohXTinBFDR/EEkjLc0="; static connect = actions; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...[ @@ -13,5 +13,4 @@ var J3w1Button = class extends J3w1Element { "tone" ]]; }; -//#endregion export { J3w1Button }; diff --git a/packages/ui/dist/components/card.js b/packages/ui/dist/components/card.js index 9981d665b..4b88cfed7 100644 --- a/packages/ui/dist/components/card.js +++ b/packages/ui/dist/components/card.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/card.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/card.js var J3w1Card = class extends J3w1Element { static componentId = "card"; static version = "4.0.0"; - static implementationId = "sha256-1zEhR7grQaSCkJEXxbq66aFLUPYuFPcwf/JnBD3tNdQ="; + static implementationId = "sha256-+1RpGzq4cNP4XbkcRsKDIZ47NkRYjt3g6rAyL67eKAg="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Card }; diff --git a/packages/ui/dist/components/chart.js b/packages/ui/dist/components/chart.js index 70d90b671..1be85f8ea 100644 --- a/packages/ui/dist/components/chart.js +++ b/packages/ui/dist/components/chart.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as chart } from "../chunks/display-Jm9bAsnb.js"; -//#region .cache/ui-build/entries/components/chart.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as chart } from "../chunks/display-l54fb8vw.js"; +// .cache/ui-build/entries/components/chart.js var J3w1Chart = class extends J3w1Element { static componentId = "chart"; static version = "4.0.0"; - static implementationId = "sha256-48dT14XNNF9ZyV4PB4oLs8zT/lNQqNt9rXZCl9gUYVc="; + static implementationId = "sha256-PhBwyLjFdcq2bXYtZewk49w7vPNGTKA3c6iz1WayLys="; static connect = chart; static upgradeProperties = [ "disabled", @@ -24,5 +24,4 @@ var J3w1Chart = class extends J3w1Element { }); } }; -//#endregion export { J3w1Chart }; diff --git a/packages/ui/dist/components/checkbox.js b/packages/ui/dist/components/checkbox.js index 8d7e19060..61ae79b4f 100644 --- a/packages/ui/dist/components/checkbox.js +++ b/packages/ui/dist/components/checkbox.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/checkbox.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/checkbox.js var J3w1Checkbox = class extends J3w1Element { static componentId = "checkbox"; static version = "4.0.0"; - static implementationId = "sha256-Izbz5fVyhrSfF5rLvCHcElWnQgwhYuvOSm5StKMlqUg="; + static implementationId = "sha256-qZohpwxrLq3iJ7JFmE0EmXgp3pJGmBpalNJzpOSs2jQ="; static connect = fields; static upgradeProperties = [ "disabled", @@ -51,5 +51,4 @@ var J3w1Checkbox = class extends J3w1Element { }); } }; -//#endregion export { J3w1Checkbox }; diff --git a/packages/ui/dist/components/chip.js b/packages/ui/dist/components/chip.js index e336b104c..3472b46ae 100644 --- a/packages/ui/dist/components/chip.js +++ b/packages/ui/dist/components/chip.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as feedback } from "../chunks/overlays-BwgpF4jI.js"; -//#region .cache/ui-build/entries/components/chip.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as feedback } from "../chunks/overlays-BW66WXLm.js"; +// .cache/ui-build/entries/components/chip.js var J3w1Chip = class extends J3w1Element { static componentId = "chip"; static version = "4.0.0"; - static implementationId = "sha256-LX8QtUNQgNJe9t+ID6Q+WinGVj68ZHfs0KLKk56qrpw="; + static implementationId = "sha256-BLhSWnVQYmMbTVx4pg3l9BbJVSN1kJ3PAmOAsCu7880="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -13,5 +13,4 @@ var J3w1Chip = class extends J3w1Element { return this._api.dismiss(...args); } }; -//#endregion export { J3w1Chip }; diff --git a/packages/ui/dist/components/code-editor.js b/packages/ui/dist/components/code-editor.js index 9a989eb60..9ded595dc 100644 --- a/packages/ui/dist/components/code-editor.js +++ b/packages/ui/dist/components/code-editor.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as developerView } from "../chunks/display-Jm9bAsnb.js"; -//#region .cache/ui-build/entries/components/code-editor.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as developerView } from "../chunks/display-l54fb8vw.js"; +// .cache/ui-build/entries/components/code-editor.js var J3w1CodeEditor = class extends J3w1Element { static componentId = "code-editor"; static version = "4.0.0"; - static implementationId = "sha256-BBPVGsJGf2n0c4gfyDdfHQH3KYYqmiAAqqC2h3DlIcc="; + static implementationId = "sha256-e/CR+QHi8ifbX2a2jAioPk485xWfjfZ+T4m6GYDGtck="; static connect = developerView; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -13,5 +13,4 @@ var J3w1CodeEditor = class extends J3w1Element { return this._api.setText(...args); } }; -//#endregion export { J3w1CodeEditor }; diff --git a/packages/ui/dist/components/combobox.js b/packages/ui/dist/components/combobox.js index 098363263..a4a6bf59f 100644 --- a/packages/ui/dist/components/combobox.js +++ b/packages/ui/dist/components/combobox.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as combobox } from "../chunks/navigation-BfNzDYZB.js"; -//#region .cache/ui-build/entries/components/combobox.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as combobox } from "../chunks/navigation-CknoksQ5.js"; +// .cache/ui-build/entries/components/combobox.js var J3w1Combobox = class extends J3w1Element { static componentId = "combobox"; static version = "4.0.0"; - static implementationId = "sha256-vBw1BDsNiy6oYSbmjgh7x2T+43b2GYa+XmHte/upgpQ="; + static implementationId = "sha256-4vDZ0Hg+y5o1gXWLagkKP/imvwnGiDolN4DHBnOP+Xo="; static connect = combobox; static upgradeProperties = [ "disabled", @@ -44,5 +44,4 @@ var J3w1Combobox = class extends J3w1Element { }); } }; -//#endregion export { J3w1Combobox }; diff --git a/packages/ui/dist/components/command-palette.js b/packages/ui/dist/components/command-palette.js index 196ad7f12..660108f21 100644 --- a/packages/ui/dist/components/command-palette.js +++ b/packages/ui/dist/components/command-palette.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as commandPalette } from "../chunks/advanced-CqBF0dSb.js"; -//#region .cache/ui-build/entries/components/command-palette.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as commandPalette } from "../chunks/advanced-BrFnVc0y.js"; +// .cache/ui-build/entries/components/command-palette.js var J3w1CommandPalette = class extends J3w1Element { static componentId = "command-palette"; static version = "4.0.0"; - static implementationId = "sha256-jnhxb+w/Xgrb5Os9Dxr1YHn/ex7fLJlGLSWZSpbrAuU="; + static implementationId = "sha256-6g0v2bCTEnlpiyCMMFs1KoDHyNPuVus2RWtD6Nlui6A="; static connect = commandPalette; static upgradeProperties = [ "disabled", @@ -36,5 +36,4 @@ var J3w1CommandPalette = class extends J3w1Element { }); } }; -//#endregion export { J3w1CommandPalette }; diff --git a/packages/ui/dist/components/compact-dashboard.js b/packages/ui/dist/components/compact-dashboard.js index b29237379..44a81ddba 100644 --- a/packages/ui/dist/components/compact-dashboard.js +++ b/packages/ui/dist/components/compact-dashboard.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as dashboard } from "../chunks/compositions-D57dCsBz.js"; -//#region .cache/ui-build/entries/components/compact-dashboard.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as dashboard } from "../chunks/compositions-DWG4tv9E.js"; +// .cache/ui-build/entries/components/compact-dashboard.js var J3w1CompactDashboard = class extends J3w1Element { static componentId = "compact-dashboard"; static version = "4.0.0"; - static implementationId = "sha256-Shp675PVGMGOiXxiKpeWEQHQugGKEIbNO/jz8KwP4m0="; + static implementationId = "sha256-XGMk6csk8qspD/G8I2T9TzGnFhunqMgxXUJbb9/81pY="; static connect = dashboard; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1CompactDashboard }; diff --git a/packages/ui/dist/components/data-table.js b/packages/ui/dist/components/data-table.js index 2825525ad..cfd4a0614 100644 --- a/packages/ui/dist/components/data-table.js +++ b/packages/ui/dist/components/data-table.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as table } from "../chunks/tables-Cjr1EIJz.js"; -//#region .cache/ui-build/entries/components/data-table.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as table } from "../chunks/tables-zo8ebTOo.js"; +// .cache/ui-build/entries/components/data-table.js var J3w1DataTable = class extends J3w1Element { static componentId = "data-table"; static version = "4.0.0"; - static implementationId = "sha256-Qlh9cF0ylT3FE8z6iBYaA9/noI1T5dVrNgulqEfZGt8="; + static implementationId = "sha256-a/glnHoeWHm3aMAVgncz982T3PIGdFT6ck7ItsOxeDk="; static connect = table; static upgradeProperties = [ "disabled", @@ -32,5 +32,4 @@ var J3w1DataTable = class extends J3w1Element { }); } }; -//#endregion export { J3w1DataTable }; diff --git a/packages/ui/dist/components/date-picker.js b/packages/ui/dist/components/date-picker.js index df35db9b0..8a93fcbc4 100644 --- a/packages/ui/dist/components/date-picker.js +++ b/packages/ui/dist/components/date-picker.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/date-picker.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/date-picker.js var J3w1DatePicker = class extends J3w1Element { static componentId = "date-picker"; static version = "4.0.0"; - static implementationId = "sha256-rz3at5sJTA4TkXHNaqQnM5BrVBt02my29UyKewvFuRY="; + static implementationId = "sha256-kmW88a2eETKKePSXhvndNd/jUUTZa5oQ4kDsL8OPCK0="; static connect = fields; static upgradeProperties = [ "disabled", @@ -27,5 +27,4 @@ var J3w1DatePicker = class extends J3w1Element { return this._api.clear(...args); } }; -//#endregion export { J3w1DatePicker }; diff --git a/packages/ui/dist/components/description-list.js b/packages/ui/dist/components/description-list.js index f7a7090ba..162d0cd1c 100644 --- a/packages/ui/dist/components/description-list.js +++ b/packages/ui/dist/components/description-list.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/description-list.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/description-list.js var J3w1DescriptionList = class extends J3w1Element { static componentId = "description-list"; static version = "4.0.0"; - static implementationId = "sha256-O3lqE1mNupuyqMqz1k1EzRDHMDjwD6aUReeED7JUclg="; + static implementationId = "sha256-DDcuNke+fAkSGnaDiAAucdChnaJzCXZYRFzSpYvEy5g="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1DescriptionList }; diff --git a/packages/ui/dist/components/diagnostics.js b/packages/ui/dist/components/diagnostics.js index f9e49175b..c59d7464f 100644 --- a/packages/ui/dist/components/diagnostics.js +++ b/packages/ui/dist/components/diagnostics.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as developerView } from "../chunks/display-Jm9bAsnb.js"; -//#region .cache/ui-build/entries/components/diagnostics.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as developerView } from "../chunks/display-l54fb8vw.js"; +// .cache/ui-build/entries/components/diagnostics.js var J3w1Diagnostics = class extends J3w1Element { static componentId = "diagnostics"; static version = "4.0.0"; - static implementationId = "sha256-lcf+xRikFjf+LQY6YZN+giWDauQWjFZbMz3xBLI3JG8="; + static implementationId = "sha256-Mh5W9ln8UtoAd11LHTHBFeXEbEIbq3SsLr4Dp7ETLtk="; static connect = developerView; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -13,5 +13,4 @@ var J3w1Diagnostics = class extends J3w1Element { return this._api.setText(...args); } }; -//#endregion export { J3w1Diagnostics }; diff --git a/packages/ui/dist/components/dialog.js b/packages/ui/dist/components/dialog.js index 3cbfc19af..f8cb9f4ed 100644 --- a/packages/ui/dist/components/dialog.js +++ b/packages/ui/dist/components/dialog.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as modal } from "../chunks/overlays-BwgpF4jI.js"; -//#region .cache/ui-build/entries/components/dialog.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as modal } from "../chunks/overlays-BW66WXLm.js"; +// .cache/ui-build/entries/components/dialog.js var J3w1Dialog = class extends J3w1Element { static componentId = "dialog"; static version = "4.0.0"; - static implementationId = "sha256-DxVkWaABviJy7mGLL8EMH80qBAY41vg1uSdV+1wlXPw="; + static implementationId = "sha256-y5bLLW2MSsvkA0D+5dWrD70gQejnbCLVcva+Y0egKag="; static connect = modal; static upgradeProperties = [ "disabled", @@ -35,5 +35,4 @@ var J3w1Dialog = class extends J3w1Element { return this._api?.returnValue; } }; -//#endregion export { J3w1Dialog }; diff --git a/packages/ui/dist/components/diff-view.js b/packages/ui/dist/components/diff-view.js index 47f8bf1a3..3daf06ec6 100644 --- a/packages/ui/dist/components/diff-view.js +++ b/packages/ui/dist/components/diff-view.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as developerView } from "../chunks/display-Jm9bAsnb.js"; -//#region .cache/ui-build/entries/components/diff-view.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as developerView } from "../chunks/display-l54fb8vw.js"; +// .cache/ui-build/entries/components/diff-view.js var J3w1DiffView = class extends J3w1Element { static componentId = "diff-view"; static version = "4.0.0"; - static implementationId = "sha256-7zzFpU0Y2cQR1wO8DWE4bqkofCnJMaERCXRLdai7u0A="; + static implementationId = "sha256-xbLfnA1/siCeNpzpHk8FA2PFnz+aDd3RON68QHJ7WnM="; static connect = developerView; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -13,5 +13,4 @@ var J3w1DiffView = class extends J3w1Element { return this._api.setText(...args); } }; -//#endregion export { J3w1DiffView }; diff --git a/packages/ui/dist/components/disclosure.js b/packages/ui/dist/components/disclosure.js index 56e4f17fd..6b8aeeb30 100644 --- a/packages/ui/dist/components/disclosure.js +++ b/packages/ui/dist/components/disclosure.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as disclosure } from "../chunks/navigation-BfNzDYZB.js"; -//#region .cache/ui-build/entries/components/disclosure.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as disclosure } from "../chunks/navigation-CknoksQ5.js"; +// .cache/ui-build/entries/components/disclosure.js var J3w1Disclosure = class extends J3w1Element { static componentId = "disclosure"; static version = "4.0.0"; - static implementationId = "sha256-h35ty1HDvIv+l1TZ2KWtUtdJetenP1x1+OVPFVOsByg="; + static implementationId = "sha256-/iZ0e5fT3U5WA2/XRKI9hazrMgnbC8vuSxv50Cf3A2g="; static connect = disclosure; static upgradeProperties = [ "disabled", @@ -24,5 +24,4 @@ var J3w1Disclosure = class extends J3w1Element { }); } }; -//#endregion export { J3w1Disclosure }; diff --git a/packages/ui/dist/components/drawer.js b/packages/ui/dist/components/drawer.js index bd2cc2719..e21fa9a5c 100644 --- a/packages/ui/dist/components/drawer.js +++ b/packages/ui/dist/components/drawer.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as modal } from "../chunks/overlays-BwgpF4jI.js"; -//#region .cache/ui-build/entries/components/drawer.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as modal } from "../chunks/overlays-BW66WXLm.js"; +// .cache/ui-build/entries/components/drawer.js var J3w1Drawer = class extends J3w1Element { static componentId = "drawer"; static version = "4.0.0"; - static implementationId = "sha256-yvpVNrlpyZhfuppx1D3pNtgoOjBrDBDX4gavOIbYSWM="; + static implementationId = "sha256-jlOQ9dUQ9/eHs5sJ9RXnG8JOrwjs9I7YeDZOvcPBU2Q="; static connect = modal; static upgradeProperties = [ "disabled", @@ -35,5 +35,4 @@ var J3w1Drawer = class extends J3w1Element { return this._api?.returnValue; } }; -//#endregion export { J3w1Drawer }; diff --git a/packages/ui/dist/components/editor-search.js b/packages/ui/dist/components/editor-search.js index fc6e2a1a7..05e2f472e 100644 --- a/packages/ui/dist/components/editor-search.js +++ b/packages/ui/dist/components/editor-search.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { i as editorSearch } from "../chunks/display-Jm9bAsnb.js"; -//#region .cache/ui-build/entries/components/editor-search.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { i as editorSearch } from "../chunks/display-l54fb8vw.js"; +// .cache/ui-build/entries/components/editor-search.js var J3w1EditorSearch = class extends J3w1Element { static componentId = "editor-search"; static version = "4.0.0"; - static implementationId = "sha256-SqX6iBMRHKvfYM9+QKkc2K/hjCGRNMeVrj+B25L3SoU="; + static implementationId = "sha256-2urZm4vBPYuucwiyIFwjQWGpodxpGnr7FqeCciyKT3M="; static connect = editorSearch; static upgradeProperties = [ "disabled", @@ -43,5 +43,4 @@ var J3w1EditorSearch = class extends J3w1Element { return this._api?.matchCount; } }; -//#endregion export { J3w1EditorSearch }; diff --git a/packages/ui/dist/components/empty-state.js b/packages/ui/dist/components/empty-state.js index 8e4944ef3..91d1cb423 100644 --- a/packages/ui/dist/components/empty-state.js +++ b/packages/ui/dist/components/empty-state.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as feedback } from "../chunks/overlays-BwgpF4jI.js"; -//#region .cache/ui-build/entries/components/empty-state.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as feedback } from "../chunks/overlays-BW66WXLm.js"; +// .cache/ui-build/entries/components/empty-state.js var J3w1EmptyState = class extends J3w1Element { static componentId = "empty-state"; static version = "4.0.0"; - static implementationId = "sha256-5BgPX4sRhOgm8ZsOZ/51exOqgz9E+QCMS8dKtOj0vGM="; + static implementationId = "sha256-0I18foHfPJW0lwhBhEhkVa29tFmqug1GlRB470z+Fc0="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -13,5 +13,4 @@ var J3w1EmptyState = class extends J3w1Element { return this._api.dismiss(...args); } }; -//#endregion export { J3w1EmptyState }; diff --git a/packages/ui/dist/components/error-state.js b/packages/ui/dist/components/error-state.js index 304fd3e2b..cbf702503 100644 --- a/packages/ui/dist/components/error-state.js +++ b/packages/ui/dist/components/error-state.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as feedback } from "../chunks/overlays-BwgpF4jI.js"; -//#region .cache/ui-build/entries/components/error-state.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as feedback } from "../chunks/overlays-BW66WXLm.js"; +// .cache/ui-build/entries/components/error-state.js var J3w1ErrorState = class extends J3w1Element { static componentId = "error-state"; static version = "4.0.0"; - static implementationId = "sha256-tOUjSBC5VAWfv+AicnePxVZaKItd4HUgjbSSn0EAnj4="; + static implementationId = "sha256-LDQJ+yUJQFusNMFvRdiX+9xXps1b5gKkDGOIKUsi3is="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -13,5 +13,4 @@ var J3w1ErrorState = class extends J3w1Element { return this._api.dismiss(...args); } }; -//#endregion export { J3w1ErrorState }; diff --git a/packages/ui/dist/components/field.js b/packages/ui/dist/components/field.js index 432885b11..22f6586d6 100644 --- a/packages/ui/dist/components/field.js +++ b/packages/ui/dist/components/field.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/field.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/field.js var J3w1Field = class extends J3w1Element { static componentId = "field"; static version = "4.0.0"; - static implementationId = "sha256-GDPT/9zMxdyqVusrML6KYJd3mC9Kts0/5zp2/Xi2cYA="; + static implementationId = "sha256-24nMRMLzw+GWacRUm+Sql7UXZ+F7xi0oVvrBEXq9G0o="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Field }; diff --git a/packages/ui/dist/components/fieldset.js b/packages/ui/dist/components/fieldset.js index 062960dc4..a37eb3884 100644 --- a/packages/ui/dist/components/fieldset.js +++ b/packages/ui/dist/components/fieldset.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/fieldset.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/fieldset.js var J3w1Fieldset = class extends J3w1Element { static componentId = "fieldset"; static version = "4.0.0"; - static implementationId = "sha256-GMEsNCLKXzxBWy1NzvLrpSNVUG/llwSmGqxbUbScbHQ="; + static implementationId = "sha256-RPx5oBBUk/CP7P0+MjMH+Vlv++S2aNxlNzAivfeo8MY="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Fieldset }; diff --git a/packages/ui/dist/components/file-browser.js b/packages/ui/dist/components/file-browser.js index 2c355a89a..697933727 100644 --- a/packages/ui/dist/components/file-browser.js +++ b/packages/ui/dist/components/file-browser.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as fileBrowser } from "../chunks/compositions-D57dCsBz.js"; -//#region .cache/ui-build/entries/components/file-browser.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as fileBrowser } from "../chunks/compositions-DWG4tv9E.js"; +// .cache/ui-build/entries/components/file-browser.js var J3w1FileBrowser = class extends J3w1Element { static componentId = "file-browser"; static version = "4.0.0"; - static implementationId = "sha256-XNnX1ARH1szUReH6kSeTR1njKOACxLiUhBCmo9iNz8s="; + static implementationId = "sha256-4K76FMxRutTXWd2WQZ21c23gbzw5z86V0UnvwDOrigI="; static connect = fileBrowser; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1FileBrowser }; diff --git a/packages/ui/dist/components/file-input.js b/packages/ui/dist/components/file-input.js index e90ea78d1..bacbe4c84 100644 --- a/packages/ui/dist/components/file-input.js +++ b/packages/ui/dist/components/file-input.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { i as fileInput } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/file-input.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { i as fileInput } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/file-input.js var J3w1FileInput = class extends J3w1Element { static componentId = "file-input"; static version = "4.0.0"; - static implementationId = "sha256-DYtJ1M3W9zNvFy3MIif27+5jsw2JssfZ5mpXTXwGBCo="; + static implementationId = "sha256-iOWh+VU40OcnTtYqrIhx4VuoRrJFI3lImsaGfHaNJew="; static connect = fileInput; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -16,5 +16,4 @@ var J3w1FileInput = class extends J3w1Element { return this._api?.files; } }; -//#endregion export { J3w1FileInput }; diff --git a/packages/ui/dist/components/filterable-table.js b/packages/ui/dist/components/filterable-table.js index 5eb0b2d55..2274cd992 100644 --- a/packages/ui/dist/components/filterable-table.js +++ b/packages/ui/dist/components/filterable-table.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as table } from "../chunks/tables-Cjr1EIJz.js"; -//#region .cache/ui-build/entries/components/filterable-table.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as table } from "../chunks/tables-zo8ebTOo.js"; +// .cache/ui-build/entries/components/filterable-table.js var J3w1FilterableTable = class extends J3w1Element { static componentId = "filterable-table"; static version = "4.0.0"; - static implementationId = "sha256-SJvvFZ+/THkuQJCx1F2i0vCQ2C54dLton+9ipWE3sS8="; + static implementationId = "sha256-n4lw+oO+89at2wpqrQKIjlpTrVj3erNy5+KxBS7zT/o="; static connect = table; static upgradeProperties = [ "disabled", @@ -32,5 +32,4 @@ var J3w1FilterableTable = class extends J3w1Element { }); } }; -//#endregion export { J3w1FilterableTable }; diff --git a/packages/ui/dist/components/form-builder.js b/packages/ui/dist/components/form-builder.js index a57aeb3e5..c5626c6d7 100644 --- a/packages/ui/dist/components/form-builder.js +++ b/packages/ui/dist/components/form-builder.js @@ -1 +1 @@ -export { t as J3w1FormBuilder } from "../chunks/form-builder-BvWZCBPR.js"; +export { t as J3w1FormBuilder } from "../chunks/form-builder-CkeTBQe-.js"; diff --git a/packages/ui/dist/components/i3-window-frame.js b/packages/ui/dist/components/i3-window-frame.js index b22fc628b..e4aebb41e 100644 --- a/packages/ui/dist/components/i3-window-frame.js +++ b/packages/ui/dist/components/i3-window-frame.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as windowFrame } from "../chunks/compositions-D57dCsBz.js"; -//#region .cache/ui-build/entries/components/i3-window-frame.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as windowFrame } from "../chunks/compositions-DWG4tv9E.js"; +// .cache/ui-build/entries/components/i3-window-frame.js var J3w1I3WindowFrame = class extends J3w1Element { static componentId = "i3-window-frame"; static version = "4.0.0"; - static implementationId = "sha256-aoVPpcLCR1nIgTxPmR2un0VYei4XlfuvYsAk1YW7+mU="; + static implementationId = "sha256-jHRA5LlE/a4NeYo7D3jGN342NIG6HXu3MWIksnZGl0o="; static connect = windowFrame; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1I3WindowFrame }; diff --git a/packages/ui/dist/components/icon-button.js b/packages/ui/dist/components/icon-button.js index 1b617c987..8feab5d80 100644 --- a/packages/ui/dist/components/icon-button.js +++ b/packages/ui/dist/components/icon-button.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as actions } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/icon-button.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as actions } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/icon-button.js var J3w1IconButton = class extends J3w1Element { static componentId = "icon-button"; static version = "4.0.0"; - static implementationId = "sha256-6B32745m5D4H8EEVZL8U0DDC44RJN37XJIm7LWa43Gg="; + static implementationId = "sha256-2sCpHP7pmi2WBuPHJmS2gW9kHYHfcKQX9rMldNFRA8M="; static connect = actions; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...[ @@ -13,5 +13,4 @@ var J3w1IconButton = class extends J3w1Element { "tone" ]]; }; -//#endregion export { J3w1IconButton }; diff --git a/packages/ui/dist/components/kbd.js b/packages/ui/dist/components/kbd.js index 0556ef474..81775d00c 100644 --- a/packages/ui/dist/components/kbd.js +++ b/packages/ui/dist/components/kbd.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/kbd.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/kbd.js var J3w1Kbd = class extends J3w1Element { static componentId = "kbd"; static version = "4.0.0"; - static implementationId = "sha256-/6a09jGbevstnOqzIMGZWFLfMuQtcqnGZ7oWyH64Xdg="; + static implementationId = "sha256-hx5b1nufTNDjDCvzk6dWzvd0aXvqZApfBtz6slhMqWY="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Kbd }; diff --git a/packages/ui/dist/components/link.js b/packages/ui/dist/components/link.js index 2356d4084..34afeeb1e 100644 --- a/packages/ui/dist/components/link.js +++ b/packages/ui/dist/components/link.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/link.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/link.js var J3w1Link = class extends J3w1Element { static componentId = "link"; static version = "4.0.0"; - static implementationId = "sha256-rEWDiPkjpyMkw7piXIpFnMc4x8xrVQVhLrBLQWgZXRM="; + static implementationId = "sha256-3rkQqxiNynw2Jw3SNY8V8khbmwWjkmKX6812xUp86hg="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Link }; diff --git a/packages/ui/dist/components/list.js b/packages/ui/dist/components/list.js index 247cffcc3..88efde471 100644 --- a/packages/ui/dist/components/list.js +++ b/packages/ui/dist/components/list.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/list.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/list.js var J3w1List = class extends J3w1Element { static componentId = "list"; static version = "4.0.0"; - static implementationId = "sha256-14u9zr26qx+pniqBnH8sp+D6R9pyXRKm+KsUR/WnsOU="; + static implementationId = "sha256-FLV30YCWvaLCp8wYMYz2Pjn6EATLZku0Y+JC3EzTq3o="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1List }; diff --git a/packages/ui/dist/components/loading-indicator.js b/packages/ui/dist/components/loading-indicator.js index 85ead853a..3d697da29 100644 --- a/packages/ui/dist/components/loading-indicator.js +++ b/packages/ui/dist/components/loading-indicator.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/loading-indicator.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/loading-indicator.js var J3w1LoadingIndicator = class extends J3w1Element { static componentId = "loading-indicator"; static version = "4.0.0"; - static implementationId = "sha256-IeUo78vKcH/jhCptrFf5Js2XH0mNmrbHQA3dBow7Sb8="; + static implementationId = "sha256-8gayEmIQL3leNhAhX4uqlnyCPN/wDa2q0DkoydIe+k0="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1LoadingIndicator }; diff --git a/packages/ui/dist/components/menu.js b/packages/ui/dist/components/menu.js index b35ceb43e..b7031703c 100644 --- a/packages/ui/dist/components/menu.js +++ b/packages/ui/dist/components/menu.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as menu } from "../chunks/navigation-BfNzDYZB.js"; -//#region .cache/ui-build/entries/components/menu.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as menu } from "../chunks/navigation-CknoksQ5.js"; +// .cache/ui-build/entries/components/menu.js var J3w1Menu = class extends J3w1Element { static componentId = "menu"; static version = "4.0.0"; - static implementationId = "sha256-oS0Ubl9rLRKcmk22aO7KDARBpUoA/Y7sR2AvyqabH+U="; + static implementationId = "sha256-eK7xkdMDWtplCwL1L9Yt83xHvFQIuO3z1yoixK4RXOo="; static connect = menu; static upgradeProperties = [ "disabled", @@ -32,5 +32,4 @@ var J3w1Menu = class extends J3w1Element { }); } }; -//#endregion export { J3w1Menu }; diff --git a/packages/ui/dist/components/multiselect.js b/packages/ui/dist/components/multiselect.js index cb58ac304..290c79dc8 100644 --- a/packages/ui/dist/components/multiselect.js +++ b/packages/ui/dist/components/multiselect.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as multiselect } from "../chunks/advanced-CqBF0dSb.js"; -//#region .cache/ui-build/entries/components/multiselect.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as multiselect } from "../chunks/advanced-BrFnVc0y.js"; +// .cache/ui-build/entries/components/multiselect.js var J3w1Multiselect = class extends J3w1Element { static componentId = "multiselect"; static version = "4.0.0"; - static implementationId = "sha256-M7eRaWl+u1uQgXFKvnBd0GCc8U7xIWfp5yT7U9eMjTg="; + static implementationId = "sha256-FXj0+g9cQaR/0ZBHov7023bXRTw6cKww+3uPo9AtwN8="; static connect = multiselect; static upgradeProperties = [ "disabled", @@ -28,5 +28,4 @@ var J3w1Multiselect = class extends J3w1Element { }); } }; -//#endregion export { J3w1Multiselect }; diff --git a/packages/ui/dist/components/number-field.js b/packages/ui/dist/components/number-field.js index 41733ea16..9efdf43c2 100644 --- a/packages/ui/dist/components/number-field.js +++ b/packages/ui/dist/components/number-field.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/number-field.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/number-field.js var J3w1NumberField = class extends J3w1Element { static componentId = "number-field"; static version = "4.0.0"; - static implementationId = "sha256-XSucS362OAqtU9RKAYp52Tc3M6K6uMWKmB6UdK8+/o0="; + static implementationId = "sha256-L91omcjZDDOb6GVo+J4RQqDwzG6TvC55C17ObqdffsA="; static connect = fields; static upgradeProperties = [ "disabled", @@ -31,5 +31,4 @@ var J3w1NumberField = class extends J3w1Element { return this._api.stepBy(...args); } }; -//#endregion export { J3w1NumberField }; diff --git a/packages/ui/dist/components/pagination.js b/packages/ui/dist/components/pagination.js index 140293f27..7423c292b 100644 --- a/packages/ui/dist/components/pagination.js +++ b/packages/ui/dist/components/pagination.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as pagination } from "../chunks/tables-Cjr1EIJz.js"; -//#region .cache/ui-build/entries/components/pagination.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as pagination } from "../chunks/tables-zo8ebTOo.js"; +// .cache/ui-build/entries/components/pagination.js var J3w1Pagination = class extends J3w1Element { static componentId = "pagination"; static version = "4.0.0"; - static implementationId = "sha256-HgWIYJ3ex0Ayw+BLic3BdN3dNV9ChkM7wiwgp/qkkAE="; + static implementationId = "sha256-MIZZYUoTVmPnN0QSV3/TqHlUbLXmXItH+lOBusJQhPQ="; static connect = pagination; static upgradeProperties = [ "disabled", @@ -24,5 +24,4 @@ var J3w1Pagination = class extends J3w1Element { }); } }; -//#endregion export { J3w1Pagination }; diff --git a/packages/ui/dist/components/popover.js b/packages/ui/dist/components/popover.js index cd98bf9db..94c3eb15a 100644 --- a/packages/ui/dist/components/popover.js +++ b/packages/ui/dist/components/popover.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as popover } from "../chunks/overlays-BwgpF4jI.js"; -//#region .cache/ui-build/entries/components/popover.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as popover } from "../chunks/overlays-BW66WXLm.js"; +// .cache/ui-build/entries/components/popover.js var J3w1Popover = class extends J3w1Element { static componentId = "popover"; static version = "4.0.0"; - static implementationId = "sha256-544d7ON825LY8X5xEBzRzpHfZ1h2hjozJQ8CIUd0dwQ="; + static implementationId = "sha256-0lpdoNXcJ4OtvOncSedDRAZh8Qqu3IC+U2AFJbsDWgo="; static connect = popover; static upgradeProperties = [ "disabled", @@ -32,5 +32,4 @@ var J3w1Popover = class extends J3w1Element { }); } }; -//#endregion export { J3w1Popover }; diff --git a/packages/ui/dist/components/progress.js b/packages/ui/dist/components/progress.js index c4664d716..ba0759904 100644 --- a/packages/ui/dist/components/progress.js +++ b/packages/ui/dist/components/progress.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/progress.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/progress.js var J3w1Progress = class extends J3w1Element { static componentId = "progress"; static version = "4.0.0"; - static implementationId = "sha256-ayNpjS/tJF/VzILGmci24aDE3GR3edKDd1sGAVN7HtQ="; + static implementationId = "sha256-akxgN48xfy+cHsPHoXeqwvAxIYp+yn0gTEmRWM0hWJE="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Progress }; diff --git a/packages/ui/dist/components/radio-group.js b/packages/ui/dist/components/radio-group.js index 9c5100135..eef0e2a61 100644 --- a/packages/ui/dist/components/radio-group.js +++ b/packages/ui/dist/components/radio-group.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/radio-group.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/radio-group.js var J3w1RadioGroup = class extends J3w1Element { static componentId = "radio-group"; static version = "4.0.0"; - static implementationId = "sha256-qoOHybVksZNlma+H614aGdgiZ/u0EegTSeDcIojBXA0="; + static implementationId = "sha256-k3eeoFy7itEt3SayQ+FY+DOTTb3EuUsTLSVncf4Pi7U="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1RadioGroup }; diff --git a/packages/ui/dist/components/range.js b/packages/ui/dist/components/range.js index b560b2a51..9cf3b5c15 100644 --- a/packages/ui/dist/components/range.js +++ b/packages/ui/dist/components/range.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/range.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/range.js var J3w1Range = class extends J3w1Element { static componentId = "range"; static version = "4.0.0"; - static implementationId = "sha256-zCJuNTps0+QV29mUu6dGnyhnpifuS7WnpWWjLJtkpdo="; + static implementationId = "sha256-i6nR59cp/+WnCt0GMdESQTDAwvHuvPWB0oPhG86AZOs="; static connect = fields; static upgradeProperties = [ "disabled", @@ -27,5 +27,4 @@ var J3w1Range = class extends J3w1Element { return this._api.clear(...args); } }; -//#endregion export { J3w1Range }; diff --git a/packages/ui/dist/components/repeater.js b/packages/ui/dist/components/repeater.js index 0874370f2..e1c1bb988 100644 --- a/packages/ui/dist/components/repeater.js +++ b/packages/ui/dist/components/repeater.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as repeater } from "../chunks/advanced-CqBF0dSb.js"; -//#region .cache/ui-build/entries/components/repeater.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as repeater } from "../chunks/advanced-BrFnVc0y.js"; +// .cache/ui-build/entries/components/repeater.js var J3w1Repeater = class extends J3w1Element { static componentId = "repeater"; static version = "4.0.0"; - static implementationId = "sha256-G3uVYtEsLo70OmMPhofMD2YylFEq1kezRvUEMrNnRII="; + static implementationId = "sha256-w4XS7/LW7dUC4L/+YrgFuI+YMBos9KBQBiuK80Uns6g="; static connect = repeater; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...[ @@ -28,5 +28,4 @@ var J3w1Repeater = class extends J3w1Element { return this._api?.rowIds; } }; -//#endregion export { J3w1Repeater }; diff --git a/packages/ui/dist/components/search-field.js b/packages/ui/dist/components/search-field.js index 666ca6dde..89b2baea5 100644 --- a/packages/ui/dist/components/search-field.js +++ b/packages/ui/dist/components/search-field.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/search-field.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/search-field.js var J3w1SearchField = class extends J3w1Element { static componentId = "search-field"; static version = "4.0.0"; - static implementationId = "sha256-nopARV2ViNiuyBqGv6KjxLJ3uaaVqRJ3K7Mgtg/mS7Q="; + static implementationId = "sha256-tI6csnLzo3YwSslahWEtsgW+3pvLdmXr4NI4noiRcxA="; static connect = fields; static upgradeProperties = [ "disabled", @@ -27,5 +27,4 @@ var J3w1SearchField = class extends J3w1Element { return this._api.clear(...args); } }; -//#endregion export { J3w1SearchField }; diff --git a/packages/ui/dist/components/segmented-control.js b/packages/ui/dist/components/segmented-control.js index 6ffc9b94e..722077482 100644 --- a/packages/ui/dist/components/segmented-control.js +++ b/packages/ui/dist/components/segmented-control.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/segmented-control.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/segmented-control.js var J3w1SegmentedControl = class extends J3w1Element { static componentId = "segmented-control"; static version = "4.0.0"; - static implementationId = "sha256-ULY50CCb++GAub0Bdb1hOwDWjDszJVNB0Fwnbmwbg1c="; + static implementationId = "sha256-WDzCMZOCx3LjXtedbEAvHx9txxgH1XLwetNqKakke+s="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1SegmentedControl }; diff --git a/packages/ui/dist/components/select.js b/packages/ui/dist/components/select.js index a59b0acab..5adb3c6f7 100644 --- a/packages/ui/dist/components/select.js +++ b/packages/ui/dist/components/select.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/select.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/select.js var J3w1Select = class extends J3w1Element { static componentId = "select"; static version = "4.0.0"; - static implementationId = "sha256-/4CAqDSF84DTC0pEcQUtcmmtAaVge6ifWVX3elTZzLM="; + static implementationId = "sha256-ghLIdVGffsPUo96JXVnI3p2L5ORJKK/Xdu7X3DOz4m0="; static connect = fields; static upgradeProperties = [ "disabled", @@ -39,5 +39,4 @@ var J3w1Select = class extends J3w1Element { }); } }; -//#endregion export { J3w1Select }; diff --git a/packages/ui/dist/components/settings-panel.js b/packages/ui/dist/components/settings-panel.js index 4d48521a3..d300eccec 100644 --- a/packages/ui/dist/components/settings-panel.js +++ b/packages/ui/dist/components/settings-panel.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as formComposition } from "../chunks/forms-CE_hP1hg.js"; -//#region .cache/ui-build/entries/components/settings-panel.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as formComposition } from "../chunks/forms-C3u5121t.js"; +// .cache/ui-build/entries/components/settings-panel.js var J3w1SettingsPanel = class extends J3w1Element { static componentId = "settings-panel"; static version = "4.0.0"; - static implementationId = "sha256-Or1edewP4Rk9HC/kFygK+IUyEoPDHJFEyWO9Acv3Ge4="; + static implementationId = "sha256-ED51an0ymCtlHkUQM0Sk0VgNjG1GK+ucBgtJAFTi2nI="; static connect = formComposition; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1SettingsPanel }; diff --git a/packages/ui/dist/components/sidebar-nav.js b/packages/ui/dist/components/sidebar-nav.js index 03f391cbd..d1c922672 100644 --- a/packages/ui/dist/components/sidebar-nav.js +++ b/packages/ui/dist/components/sidebar-nav.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as disclosure } from "../chunks/navigation-BfNzDYZB.js"; -//#region .cache/ui-build/entries/components/sidebar-nav.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as disclosure } from "../chunks/navigation-CknoksQ5.js"; +// .cache/ui-build/entries/components/sidebar-nav.js var J3w1SidebarNav = class extends J3w1Element { static componentId = "sidebar-nav"; static version = "4.0.0"; - static implementationId = "sha256-rKjBWaKv0/VZBCTIvYNnUx/X/HyPypn7MJrL9+nt6cM="; + static implementationId = "sha256-p1RculkZB6rOKcsc85xvS+ftYOHY9F7U48/gV/8p3dk="; static connect = disclosure; static upgradeProperties = [ "disabled", @@ -24,5 +24,4 @@ var J3w1SidebarNav = class extends J3w1Element { }); } }; -//#endregion export { J3w1SidebarNav }; diff --git a/packages/ui/dist/components/skeleton.js b/packages/ui/dist/components/skeleton.js index 16c0393a3..048e9f976 100644 --- a/packages/ui/dist/components/skeleton.js +++ b/packages/ui/dist/components/skeleton.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/skeleton.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/skeleton.js var J3w1Skeleton = class extends J3w1Element { static componentId = "skeleton"; static version = "4.0.0"; - static implementationId = "sha256-ZyHv2dS6YAfZGShU1uHi9YjORc4siAkmG4ledp4rX5I="; + static implementationId = "sha256-a+nQWoa3UR7bvtD3UARr6/n5WMa+YIA0/LDJorNqkN8="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Skeleton }; diff --git a/packages/ui/dist/components/skip-link.js b/packages/ui/dist/components/skip-link.js index 65021bd9d..6731a0c7a 100644 --- a/packages/ui/dist/components/skip-link.js +++ b/packages/ui/dist/components/skip-link.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/skip-link.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/skip-link.js var J3w1SkipLink = class extends J3w1Element { static componentId = "skip-link"; static version = "4.0.0"; - static implementationId = "sha256-S77cz706XKgfI8OMLIyAhZab0PRCJkMplNQrcZjKP3c="; + static implementationId = "sha256-m2YbsLKFuE2LVJUIBlNoW28ON58/n56665mSGjucoHw="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1SkipLink }; diff --git a/packages/ui/dist/components/switch.js b/packages/ui/dist/components/switch.js index 87c027482..5ca2e4f1d 100644 --- a/packages/ui/dist/components/switch.js +++ b/packages/ui/dist/components/switch.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { a as switchControl } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/switch.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { a as switchControl } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/switch.js var J3w1Switch = class extends J3w1Element { static componentId = "switch"; static version = "4.0.0"; - static implementationId = "sha256-FqTv7TNhvOBWq10QKBC1FBB+4Wxd4wo2qtt4bCUEvbA="; + static implementationId = "sha256-uj6lpt+JpOZ3eT8oXJm21YGJarcQjDoXnm/GwDmQmcI="; static connect = switchControl; static upgradeProperties = [ "disabled", @@ -29,5 +29,4 @@ var J3w1Switch = class extends J3w1Element { }); } }; -//#endregion export { J3w1Switch }; diff --git a/packages/ui/dist/components/table.js b/packages/ui/dist/components/table.js index a79632ad4..7d00b4972 100644 --- a/packages/ui/dist/components/table.js +++ b/packages/ui/dist/components/table.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as table } from "../chunks/tables-Cjr1EIJz.js"; -//#region .cache/ui-build/entries/components/table.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as table } from "../chunks/tables-zo8ebTOo.js"; +// .cache/ui-build/entries/components/table.js var J3w1Table = class extends J3w1Element { static componentId = "table"; static version = "4.0.0"; - static implementationId = "sha256-dYinCl3vod1TSMh+SSPtibWEFlVRwhAF7TZ09eviokw="; + static implementationId = "sha256-qzueems4nlIVXm/5XT2r1R4us1YNkmAFjQkeOBgWPiM="; static connect = table; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -17,5 +17,4 @@ var J3w1Table = class extends J3w1Element { return this._api.filter(...args); } }; -//#endregion export { J3w1Table }; diff --git a/packages/ui/dist/components/tabs.js b/packages/ui/dist/components/tabs.js index 448e73b8b..7538c6ae4 100644 --- a/packages/ui/dist/components/tabs.js +++ b/packages/ui/dist/components/tabs.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { i as tabs } from "../chunks/navigation-BfNzDYZB.js"; -//#region .cache/ui-build/entries/components/tabs.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { i as tabs } from "../chunks/navigation-CknoksQ5.js"; +// .cache/ui-build/entries/components/tabs.js var J3w1Tabs = class extends J3w1Element { static componentId = "tabs"; static version = "4.0.0"; - static implementationId = "sha256-vWyT4Mr1GxnXVkpNXHK/nd/+0BmdRogsb7+eE6EnQ7A="; + static implementationId = "sha256-264IAmFxjdMOK5kPIhdYJogO9fMeVwBYQiMzGB9GxdU="; static connect = tabs; static upgradeProperties = [ "disabled", @@ -32,5 +32,4 @@ var J3w1Tabs = class extends J3w1Element { }); } }; -//#endregion export { J3w1Tabs }; diff --git a/packages/ui/dist/components/terminal.js b/packages/ui/dist/components/terminal.js index d9c12358a..69f99fbca 100644 --- a/packages/ui/dist/components/terminal.js +++ b/packages/ui/dist/components/terminal.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as developerView } from "../chunks/display-Jm9bAsnb.js"; -//#region .cache/ui-build/entries/components/terminal.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as developerView } from "../chunks/display-l54fb8vw.js"; +// .cache/ui-build/entries/components/terminal.js var J3w1Terminal = class extends J3w1Element { static componentId = "terminal"; static version = "4.0.0"; - static implementationId = "sha256-vnYvMfEFdH6UbGXHQ5OrfeJTspczt8hiaTWYnXnhlJc="; + static implementationId = "sha256-EaWsX7/hfvpbco1yseFqk/elrH1deuvBKjBPCqnnO2A="; static connect = developerView; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -13,5 +13,4 @@ var J3w1Terminal = class extends J3w1Element { return this._api.setText(...args); } }; -//#endregion export { J3w1Terminal }; diff --git a/packages/ui/dist/components/text-field.js b/packages/ui/dist/components/text-field.js index 5f6946538..bfc3476ad 100644 --- a/packages/ui/dist/components/text-field.js +++ b/packages/ui/dist/components/text-field.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/text-field.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/text-field.js var J3w1TextField = class extends J3w1Element { static componentId = "text-field"; static version = "4.0.0"; - static implementationId = "sha256-k06i0LBPa/oPe2VNmxbJkBzisp1zcAENq3MeVnKZzAo="; + static implementationId = "sha256-/LAwaTyhlpYQI8437cVvaHxrflDBWGv7PN7EEfW2aSE="; static connect = fields; static upgradeProperties = [ "disabled", @@ -31,5 +31,4 @@ var J3w1TextField = class extends J3w1Element { return this._api.stepBy(...args); } }; -//#endregion export { J3w1TextField }; diff --git a/packages/ui/dist/components/textarea.js b/packages/ui/dist/components/textarea.js index 850762b41..bb600b3d9 100644 --- a/packages/ui/dist/components/textarea.js +++ b/packages/ui/dist/components/textarea.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/textarea.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/textarea.js var J3w1Textarea = class extends J3w1Element { static componentId = "textarea"; static version = "4.0.0"; - static implementationId = "sha256-BoVEmVsZUWTLPVMKc4WLoQfNpjGc4Wy8j7o7zHck1uQ="; + static implementationId = "sha256-N6gpTKdWZilxDYkj8So4jkvfInVXt3HlRRVVtkRkqsM="; static connect = fields; static upgradeProperties = [ "disabled", @@ -27,5 +27,4 @@ var J3w1Textarea = class extends J3w1Element { return this._api.clear(...args); } }; -//#endregion export { J3w1Textarea }; diff --git a/packages/ui/dist/components/time-picker.js b/packages/ui/dist/components/time-picker.js index 182becce4..d34ef01e1 100644 --- a/packages/ui/dist/components/time-picker.js +++ b/packages/ui/dist/components/time-picker.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/time-picker.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/time-picker.js var J3w1TimePicker = class extends J3w1Element { static componentId = "time-picker"; static version = "4.0.0"; - static implementationId = "sha256-IYFVpO+yyMztyk5IQgkfuuyrieY/xyLgcisHM1D02DA="; + static implementationId = "sha256-EhUMFyx8J5zlwkM0jR2I+gtvKReYxpzngJ3xpfIzS7E="; static connect = fields; static upgradeProperties = [ "disabled", @@ -27,5 +27,4 @@ var J3w1TimePicker = class extends J3w1Element { return this._api.clear(...args); } }; -//#endregion export { J3w1TimePicker }; diff --git a/packages/ui/dist/components/timeline.js b/packages/ui/dist/components/timeline.js index b5e0249ea..749602508 100644 --- a/packages/ui/dist/components/timeline.js +++ b/packages/ui/dist/components/timeline.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/timeline.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/timeline.js var J3w1Timeline = class extends J3w1Element { static componentId = "timeline"; static version = "4.0.0"; - static implementationId = "sha256-AeDLITSMVmcqyJwXO1iz+6eWe9/9kWYL6lepUxS5ZtU="; + static implementationId = "sha256-p2Koxe1oSG3IRYJ6sKk+H6cBn3AC7H+5Goi4No5rZ+Y="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Timeline }; diff --git a/packages/ui/dist/components/toast.js b/packages/ui/dist/components/toast.js index 46f24a535..905544ae0 100644 --- a/packages/ui/dist/components/toast.js +++ b/packages/ui/dist/components/toast.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as feedback } from "../chunks/overlays-BwgpF4jI.js"; -//#region .cache/ui-build/entries/components/toast.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as feedback } from "../chunks/overlays-BW66WXLm.js"; +// .cache/ui-build/entries/components/toast.js var J3w1Toast = class extends J3w1Element { static componentId = "toast"; static version = "4.0.0"; - static implementationId = "sha256-j9WKre9usZOe/7NyvL2T/LvVxN+aLguS4DKMT0466EQ="; + static implementationId = "sha256-ywJbcX+iwfyImi8hYwyUwIemYNa3TJIvKqVcolt3uzE="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -13,5 +13,4 @@ var J3w1Toast = class extends J3w1Element { return this._api.dismiss(...args); } }; -//#endregion export { J3w1Toast }; diff --git a/packages/ui/dist/components/toolbar.js b/packages/ui/dist/components/toolbar.js index 195494e1d..ab307309b 100644 --- a/packages/ui/dist/components/toolbar.js +++ b/packages/ui/dist/components/toolbar.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { a as toolbar } from "../chunks/navigation-BfNzDYZB.js"; -//#region .cache/ui-build/entries/components/toolbar.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { a as toolbar } from "../chunks/navigation-CknoksQ5.js"; +// .cache/ui-build/entries/components/toolbar.js var J3w1Toolbar = class extends J3w1Element { static componentId = "toolbar"; static version = "4.0.0"; - static implementationId = "sha256-VCE2y9mKILLuKe6e6CYb+KzHmhM/oKWGD3XWHaHGRw0="; + static implementationId = "sha256-MH79RqtTV8lNFKQ+8OCjx7laob8pZbNEXeokabRaYPg="; static connect = toolbar; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Toolbar }; diff --git a/packages/ui/dist/components/tooltip.js b/packages/ui/dist/components/tooltip.js index d592891f8..c63418332 100644 --- a/packages/ui/dist/components/tooltip.js +++ b/packages/ui/dist/components/tooltip.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { i as tooltip } from "../chunks/overlays-BwgpF4jI.js"; -//#region .cache/ui-build/entries/components/tooltip.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { i as tooltip } from "../chunks/overlays-BW66WXLm.js"; +// .cache/ui-build/entries/components/tooltip.js var J3w1Tooltip = class extends J3w1Element { static componentId = "tooltip"; static version = "4.0.0"; - static implementationId = "sha256-lBUCe8gBEWWTZ/ovJn9Q/43pRaM2mAdooaxpLQzBDFE="; + static implementationId = "sha256-tg/pFgfIVuB/fXKZ8eGMFx45dRWdM2lYpc9vKsFgM8M="; static connect = tooltip; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -20,5 +20,4 @@ var J3w1Tooltip = class extends J3w1Element { return this._api?.open; } }; -//#endregion export { J3w1Tooltip }; diff --git a/packages/ui/dist/components/tree.js b/packages/ui/dist/components/tree.js index e0f6bd8da..d64ee41f2 100644 --- a/packages/ui/dist/components/tree.js +++ b/packages/ui/dist/components/tree.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { i as tree } from "../chunks/advanced-CqBF0dSb.js"; -//#region .cache/ui-build/entries/components/tree.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { i as tree } from "../chunks/advanced-BrFnVc0y.js"; +// .cache/ui-build/entries/components/tree.js var J3w1Tree = class extends J3w1Element { static componentId = "tree"; static version = "4.0.0"; - static implementationId = "sha256-8E6bGMMWEmhgjIAfuDs1+pxcabRicShQao3beIvcNBY="; + static implementationId = "sha256-4tyCeiJO1ktFeL6tRtS1nNUZhSguTNcVzLun9Gw4gX0="; static connect = tree; static upgradeProperties = [ "disabled", @@ -28,5 +28,4 @@ var J3w1Tree = class extends J3w1Element { }); } }; -//#endregion export { J3w1Tree }; diff --git a/packages/ui/dist/components/wizard.js b/packages/ui/dist/components/wizard.js index 852097735..775e64794 100644 --- a/packages/ui/dist/components/wizard.js +++ b/packages/ui/dist/components/wizard.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as wizard } from "../chunks/forms-CE_hP1hg.js"; -//#region .cache/ui-build/entries/components/wizard.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as wizard } from "../chunks/forms-C3u5121t.js"; +// .cache/ui-build/entries/components/wizard.js var J3w1Wizard = class extends J3w1Element { static componentId = "wizard"; static version = "4.0.0"; - static implementationId = "sha256-RPzZPFnWZYndDTCn4JxgWR8s+kGEDCPgKxzzaesMZdk="; + static implementationId = "sha256-wTcu4zP0i8kvSlxtwGFtrYx/9baiKjAH6nC33cNC3v8="; static connect = wizard; static upgradeProperties = [ "disabled", @@ -32,5 +32,4 @@ var J3w1Wizard = class extends J3w1Element { }); } }; -//#endregion export { J3w1Wizard }; diff --git a/packages/ui/dist/contracts/admin-form.json b/packages/ui/dist/contracts/admin-form.json index d1312f1a2..15648bf40 100644 --- a/packages/ui/dist/contracts/admin-form.json +++ b/packages/ui/dist/contracts/admin-form.json @@ -913,6 +913,6 @@ "copy": { "directory": "copy/admin-form/", "manifest": "copy/admin-form/manifest.json", - "digest": "sha256-qLocGmsNdOM4Kxf0Fo73ND/8SXaknuN2y2Z2ZwG/FL0=" + "digest": "sha256-CZpsDr9vBVqJHzKFBNQ1rV6Hp2i7SX0FCfV36645rM0=" } } diff --git a/packages/ui/dist/contracts/alert.json b/packages/ui/dist/contracts/alert.json index 44eeae171..43d1b9c55 100644 --- a/packages/ui/dist/contracts/alert.json +++ b/packages/ui/dist/contracts/alert.json @@ -446,6 +446,6 @@ "copy": { "directory": "copy/alert/", "manifest": "copy/alert/manifest.json", - "digest": "sha256-WUBXZH3wEKDy2fuHpMItmwzDupMwJWkHiSFgo4bgJiY=" + "digest": "sha256-InLGG3IWFONsGn5KCD24pSHkaUnfTaYX2B6SIBqEZpA=" } } diff --git a/packages/ui/dist/contracts/avatar.json b/packages/ui/dist/contracts/avatar.json index 4212278fb..3638155f3 100644 --- a/packages/ui/dist/contracts/avatar.json +++ b/packages/ui/dist/contracts/avatar.json @@ -273,6 +273,6 @@ "copy": { "directory": "copy/avatar/", "manifest": "copy/avatar/manifest.json", - "digest": "sha256-h6E9Gq/zG5cpoR8salWCBZib2LAeN/HoEWUAjUuO1eM=" + "digest": "sha256-ilxLEKfMT5nFnj36Q8EbpTR2cUsrKtPqehskB4kYJJA=" } } diff --git a/packages/ui/dist/contracts/badge.json b/packages/ui/dist/contracts/badge.json index a54b2151a..ce745ba8b 100644 --- a/packages/ui/dist/contracts/badge.json +++ b/packages/ui/dist/contracts/badge.json @@ -452,6 +452,6 @@ "copy": { "directory": "copy/badge/", "manifest": "copy/badge/manifest.json", - "digest": "sha256-EQLMi+/s/9/r4jBUNqLLHB9a4hXAxwdJbe0EwruBchU=" + "digest": "sha256-bkgRLHr49b5qbJcZfXpVEjzzhdlPw3nsw13B1W5ooWE=" } } diff --git a/packages/ui/dist/contracts/breadcrumbs.json b/packages/ui/dist/contracts/breadcrumbs.json index eff3f7f54..75ebc6a4b 100644 --- a/packages/ui/dist/contracts/breadcrumbs.json +++ b/packages/ui/dist/contracts/breadcrumbs.json @@ -332,6 +332,6 @@ "copy": { "directory": "copy/breadcrumbs/", "manifest": "copy/breadcrumbs/manifest.json", - "digest": "sha256-PnPBWuAuuwRQb41eezSDdJeQfhCsDD51EPmo4ROi/oQ=" + "digest": "sha256-CJpFbChWwRbAs6PLzZCwhgnD6Rd9eel8zHWhRjHQ/14=" } } diff --git a/packages/ui/dist/contracts/button-group.json b/packages/ui/dist/contracts/button-group.json index 30fd1e1c9..5df2b8295 100644 --- a/packages/ui/dist/contracts/button-group.json +++ b/packages/ui/dist/contracts/button-group.json @@ -522,6 +522,6 @@ "copy": { "directory": "copy/button-group/", "manifest": "copy/button-group/manifest.json", - "digest": "sha256-OV9ljuCQx8r8eDk+U9iS1DT7aSUPtvKcipUl75sYW1s=" + "digest": "sha256-Oj60S70C3/4Fcn4PirxNRaULxvlKmJFSmjikxcLT+6s=" } } diff --git a/packages/ui/dist/contracts/button.json b/packages/ui/dist/contracts/button.json index 08be70e15..709742a32 100644 --- a/packages/ui/dist/contracts/button.json +++ b/packages/ui/dist/contracts/button.json @@ -512,6 +512,6 @@ "copy": { "directory": "copy/button/", "manifest": "copy/button/manifest.json", - "digest": "sha256-W2vgMYD1GCX3nA8jySc1GPBP93dPoIbu2ppqti6N/Bg=" + "digest": "sha256-vW6Doqi2/lmML0KV+cfq8S3WWL8tJ5SOwdkafLEblDU=" } } diff --git a/packages/ui/dist/contracts/card.json b/packages/ui/dist/contracts/card.json index d7fda9148..728ee6801 100644 --- a/packages/ui/dist/contracts/card.json +++ b/packages/ui/dist/contracts/card.json @@ -376,6 +376,6 @@ "copy": { "directory": "copy/card/", "manifest": "copy/card/manifest.json", - "digest": "sha256-1wGcxPvwkLOFG+/IrgcVNc7OWwpt9Vt5X40wEJxgHYs=" + "digest": "sha256-+ZDgWqa1Gm0/ZbS3kd5tiksKBofhb6/lIpaH3DyKg8c=" } } diff --git a/packages/ui/dist/contracts/chart.json b/packages/ui/dist/contracts/chart.json index cd46edee6..6347b49fa 100644 --- a/packages/ui/dist/contracts/chart.json +++ b/packages/ui/dist/contracts/chart.json @@ -335,6 +335,6 @@ "copy": { "directory": "copy/chart/", "manifest": "copy/chart/manifest.json", - "digest": "sha256-Or49KDdppCAKuoF2lIsC5y+XTd9Y4F5NIW2CvpmIBgE=" + "digest": "sha256-Est3Gqn/L2c6gQ/ktXWGmG9Y2cwcaPVG7AIrl0KfXMA=" } } diff --git a/packages/ui/dist/contracts/checkbox.json b/packages/ui/dist/contracts/checkbox.json index 20fe14619..b11f730c8 100644 --- a/packages/ui/dist/contracts/checkbox.json +++ b/packages/ui/dist/contracts/checkbox.json @@ -492,6 +492,6 @@ "copy": { "directory": "copy/checkbox/", "manifest": "copy/checkbox/manifest.json", - "digest": "sha256-JI8rTznen/f8jQhHRPNS9DIrpFO2Xy3aEhj534QeX6k=" + "digest": "sha256-/ZoXbFntvWo05tyf1uBWkVt4qrFshxfjHstu3kJCQ7g=" } } diff --git a/packages/ui/dist/contracts/chip.json b/packages/ui/dist/contracts/chip.json index ebab63b66..99eba78b9 100644 --- a/packages/ui/dist/contracts/chip.json +++ b/packages/ui/dist/contracts/chip.json @@ -374,6 +374,6 @@ "copy": { "directory": "copy/chip/", "manifest": "copy/chip/manifest.json", - "digest": "sha256-G6wsd9o4sObyBn2pSMbPZcb2tX61tF6Ie4kt26HgIDA=" + "digest": "sha256-CU5wNUKgI2FlTYYXz6aqRGpR7umv1yBDqnIBuABcsFA=" } } diff --git a/packages/ui/dist/contracts/code-editor.json b/packages/ui/dist/contracts/code-editor.json index 8f1d712e7..2d7b6fe87 100644 --- a/packages/ui/dist/contracts/code-editor.json +++ b/packages/ui/dist/contracts/code-editor.json @@ -533,6 +533,6 @@ "copy": { "directory": "copy/code-editor/", "manifest": "copy/code-editor/manifest.json", - "digest": "sha256-OINO1eXNSuTLSRe6ibFtS+KeQIlXQmszvJpDmyx0/xs=" + "digest": "sha256-zLyZ3TTrERwSfzkV2jv+eEH2zYN8S67pbrLxiPokZ8g=" } } diff --git a/packages/ui/dist/contracts/combobox.json b/packages/ui/dist/contracts/combobox.json index b93212c00..fe962906b 100644 --- a/packages/ui/dist/contracts/combobox.json +++ b/packages/ui/dist/contracts/combobox.json @@ -543,6 +543,6 @@ "copy": { "directory": "copy/combobox/", "manifest": "copy/combobox/manifest.json", - "digest": "sha256-JN1xqFQwRlRkbdXeaWnCDAO5xaE514+8b2SFoCppq1I=" + "digest": "sha256-BHwUvX1X6Rgb3rs2Pc1sNQvqeTdHabf6SjFGk2AmU1M=" } } diff --git a/packages/ui/dist/contracts/command-palette.json b/packages/ui/dist/contracts/command-palette.json index 68589b589..16dd279c2 100644 --- a/packages/ui/dist/contracts/command-palette.json +++ b/packages/ui/dist/contracts/command-palette.json @@ -630,6 +630,6 @@ "copy": { "directory": "copy/command-palette/", "manifest": "copy/command-palette/manifest.json", - "digest": "sha256-tjArMCNHId+SnS0f3ur35httBepWV8sCymDinMsnVjo=" + "digest": "sha256-XlHU7U8vdCo8JeGY0CcOe8/lMvOWTLcOQbJYUToe8FI=" } } diff --git a/packages/ui/dist/contracts/compact-dashboard.json b/packages/ui/dist/contracts/compact-dashboard.json index d64503c31..61bf0e635 100644 --- a/packages/ui/dist/contracts/compact-dashboard.json +++ b/packages/ui/dist/contracts/compact-dashboard.json @@ -653,6 +653,6 @@ "copy": { "directory": "copy/compact-dashboard/", "manifest": "copy/compact-dashboard/manifest.json", - "digest": "sha256-jRq9uUQPaE37uiQUdKCVIiu16eHtJBqT2iZWAa/5iQQ=" + "digest": "sha256-NNCsh/fxXpIMYEIuWrUTU92MV0xi/Q8eV8i9hhkDveo=" } } diff --git a/packages/ui/dist/contracts/data-table.json b/packages/ui/dist/contracts/data-table.json index 139ee13bd..6df825fff 100644 --- a/packages/ui/dist/contracts/data-table.json +++ b/packages/ui/dist/contracts/data-table.json @@ -579,6 +579,6 @@ "copy": { "directory": "copy/data-table/", "manifest": "copy/data-table/manifest.json", - "digest": "sha256-ZXpisN2sD2A6zlORJ12emoU2f8SpPNEjy3p0bGcsbIk=" + "digest": "sha256-wRKFbyntVQNJhwQa94bAviNO85PO/U2WEgopjQS5mKM=" } } diff --git a/packages/ui/dist/contracts/date-picker.json b/packages/ui/dist/contracts/date-picker.json index 183aea5bd..feb9e00c0 100644 --- a/packages/ui/dist/contracts/date-picker.json +++ b/packages/ui/dist/contracts/date-picker.json @@ -580,6 +580,6 @@ "copy": { "directory": "copy/date-picker/", "manifest": "copy/date-picker/manifest.json", - "digest": "sha256-LiBwzgSr30/e/fN9ddg+q4sCYu9syKXj3tCBtq107No=" + "digest": "sha256-CxVQPORtGZItCKJdZW0KeB38sjR2gai9Y8SoJz/pE9k=" } } diff --git a/packages/ui/dist/contracts/description-list.json b/packages/ui/dist/contracts/description-list.json index e69c08d3d..37971fa05 100644 --- a/packages/ui/dist/contracts/description-list.json +++ b/packages/ui/dist/contracts/description-list.json @@ -278,6 +278,6 @@ "copy": { "directory": "copy/description-list/", "manifest": "copy/description-list/manifest.json", - "digest": "sha256-xpP/lv9etnoSHKftX4rqUvDlQ1KZY0EeEjnYOHqyD1A=" + "digest": "sha256-g7R20basqOzoGcQG1wExdudMw/U/b406QmhHIKvRdeA=" } } diff --git a/packages/ui/dist/contracts/diagnostics.json b/packages/ui/dist/contracts/diagnostics.json index 8dca223be..a9b7e8915 100644 --- a/packages/ui/dist/contracts/diagnostics.json +++ b/packages/ui/dist/contracts/diagnostics.json @@ -559,6 +559,6 @@ "copy": { "directory": "copy/diagnostics/", "manifest": "copy/diagnostics/manifest.json", - "digest": "sha256-/tKvGRBc6hhqnfZJ7dYirqMb358NCxUY8e4KhG4y9j0=" + "digest": "sha256-gGsegK/zB/UXWJ1b0OAHgz/8LfomuJdrZMd2N7SuRNg=" } } diff --git a/packages/ui/dist/contracts/dialog.json b/packages/ui/dist/contracts/dialog.json index 4d9c27b6d..36d1a15b9 100644 --- a/packages/ui/dist/contracts/dialog.json +++ b/packages/ui/dist/contracts/dialog.json @@ -700,6 +700,6 @@ "copy": { "directory": "copy/dialog/", "manifest": "copy/dialog/manifest.json", - "digest": "sha256-K7i7iL46BCLXqiyFk9t8rU9BYhfn0lNPuOnIrHnuA5o=" + "digest": "sha256-TSbiYeFvJMF2U6hGsE8nbaJyAV0b70JabFzXr6ix2rM=" } } diff --git a/packages/ui/dist/contracts/diff-view.json b/packages/ui/dist/contracts/diff-view.json index 06ee84656..91b84c2fd 100644 --- a/packages/ui/dist/contracts/diff-view.json +++ b/packages/ui/dist/contracts/diff-view.json @@ -505,6 +505,6 @@ "copy": { "directory": "copy/diff-view/", "manifest": "copy/diff-view/manifest.json", - "digest": "sha256-9Y803JsNKTzO9FZrSrjpWhyIAFnC0ZGfnQWxqX0Mz/w=" + "digest": "sha256-umOsaI8V2Tt1tM7OwzbtZlpPW29lyWQpQU3vyS01Adg=" } } diff --git a/packages/ui/dist/contracts/disclosure.json b/packages/ui/dist/contracts/disclosure.json index 043fe1405..44a33e7b3 100644 --- a/packages/ui/dist/contracts/disclosure.json +++ b/packages/ui/dist/contracts/disclosure.json @@ -303,6 +303,6 @@ "copy": { "directory": "copy/disclosure/", "manifest": "copy/disclosure/manifest.json", - "digest": "sha256-pMODL78LTWx5czys20cATaHYiUuOfzpWx9mq9jiVF6k=" + "digest": "sha256-R1qmwlzIBtRZDG/qaSsnPxCudK0VFECAfn8jGjFtV4I=" } } diff --git a/packages/ui/dist/contracts/drawer.json b/packages/ui/dist/contracts/drawer.json index 08a6e4b2c..c74383f91 100644 --- a/packages/ui/dist/contracts/drawer.json +++ b/packages/ui/dist/contracts/drawer.json @@ -695,6 +695,6 @@ "copy": { "directory": "copy/drawer/", "manifest": "copy/drawer/manifest.json", - "digest": "sha256-SyjiZGfW7kf4vufRk3oLDjiS7zw5VEwkSWdPMt7GjaI=" + "digest": "sha256-yJbahCQlijj7/ZMLUN+3jSfKlLEZy5cgMCTZznnd7ok=" } } diff --git a/packages/ui/dist/contracts/editor-search.json b/packages/ui/dist/contracts/editor-search.json index 4ab56e196..ad9e122da 100644 --- a/packages/ui/dist/contracts/editor-search.json +++ b/packages/ui/dist/contracts/editor-search.json @@ -578,6 +578,6 @@ "copy": { "directory": "copy/editor-search/", "manifest": "copy/editor-search/manifest.json", - "digest": "sha256-1TxEf5DD4kNTVifj65tU5NzGDOhBTser7acFaOPlY+Y=" + "digest": "sha256-A06+dBDdDT2cYEvZUmajvJpMDPBzS4T26NYL7uorb0s=" } } diff --git a/packages/ui/dist/contracts/empty-state.json b/packages/ui/dist/contracts/empty-state.json index ab7a8e587..b53f853ad 100644 --- a/packages/ui/dist/contracts/empty-state.json +++ b/packages/ui/dist/contracts/empty-state.json @@ -569,6 +569,6 @@ "copy": { "directory": "copy/empty-state/", "manifest": "copy/empty-state/manifest.json", - "digest": "sha256-ubp6C9NL9OCyq6QLT556NHrWxWfehrZJwTjOfOkr4wU=" + "digest": "sha256-cvIfK+Ds7EzrT7+nTFN0wNCb/+G0YJLKPKgfySV/7CI=" } } diff --git a/packages/ui/dist/contracts/error-state.json b/packages/ui/dist/contracts/error-state.json index 6c7fa2c1b..eaae3da31 100644 --- a/packages/ui/dist/contracts/error-state.json +++ b/packages/ui/dist/contracts/error-state.json @@ -550,6 +550,6 @@ "copy": { "directory": "copy/error-state/", "manifest": "copy/error-state/manifest.json", - "digest": "sha256-pZSXraMAM3LPuhv/6n3+7FR5RxqyhkPxwUX/iFdIWSM=" + "digest": "sha256-JVn20IIGWKkLSG9VQVc1nUrIgYpvJMLvi5nFiu2hg50=" } } diff --git a/packages/ui/dist/contracts/field.json b/packages/ui/dist/contracts/field.json index aed2e5ee5..a030f0a2b 100644 --- a/packages/ui/dist/contracts/field.json +++ b/packages/ui/dist/contracts/field.json @@ -372,6 +372,6 @@ "copy": { "directory": "copy/field/", "manifest": "copy/field/manifest.json", - "digest": "sha256-LpNdRh0ag+40WP0osnDPicBeZVJCfyJFNw5hveNtVGE=" + "digest": "sha256-7nP3BG+2sl/bArEWKUNRs85KiQVcdaxY8HLZ9HhQT0A=" } } diff --git a/packages/ui/dist/contracts/fieldset.json b/packages/ui/dist/contracts/fieldset.json index 54fb1334f..4975ab799 100644 --- a/packages/ui/dist/contracts/fieldset.json +++ b/packages/ui/dist/contracts/fieldset.json @@ -369,6 +369,6 @@ "copy": { "directory": "copy/fieldset/", "manifest": "copy/fieldset/manifest.json", - "digest": "sha256-N+k1sOyc1xn9mQPzsrZ2PMYAWXFZcnELwGvileR+b/I=" + "digest": "sha256-YNW+PoKZwohuqWHAcQWYxQOGTXR6y+pebqXA3PZj918=" } } diff --git a/packages/ui/dist/contracts/file-browser.json b/packages/ui/dist/contracts/file-browser.json index e3455c0e7..9aab199c8 100644 --- a/packages/ui/dist/contracts/file-browser.json +++ b/packages/ui/dist/contracts/file-browser.json @@ -627,6 +627,6 @@ "copy": { "directory": "copy/file-browser/", "manifest": "copy/file-browser/manifest.json", - "digest": "sha256-7lqHULQBVMHEaRp9C8gbDNfM8EG6QEtHgdKA45i3mKM=" + "digest": "sha256-MFkY0L5JDWoFk1lcMG7lcv7LxWhxgiGTofrx8pVTIIo=" } } diff --git a/packages/ui/dist/contracts/file-input.json b/packages/ui/dist/contracts/file-input.json index 957505d20..84ed514d1 100644 --- a/packages/ui/dist/contracts/file-input.json +++ b/packages/ui/dist/contracts/file-input.json @@ -621,6 +621,6 @@ "copy": { "directory": "copy/file-input/", "manifest": "copy/file-input/manifest.json", - "digest": "sha256-jCusOPGk/wROmZERAJfrwjFsdbxWEW0umySlqp/dE2U=" + "digest": "sha256-UjWbK5yz9uM7Cug83FXK3r5b3ow6dJz0Cjc3Y7PUCiU=" } } diff --git a/packages/ui/dist/contracts/filterable-table.json b/packages/ui/dist/contracts/filterable-table.json index f612b4992..1122ba026 100644 --- a/packages/ui/dist/contracts/filterable-table.json +++ b/packages/ui/dist/contracts/filterable-table.json @@ -745,6 +745,6 @@ "copy": { "directory": "copy/filterable-table/", "manifest": "copy/filterable-table/manifest.json", - "digest": "sha256-241aHbTVmM2Zm6n7I+iXIVUlp/cFG7Sms6dBmoCL5w0=" + "digest": "sha256-Oq9HQCEheDtWrjOzkY+U+/553gCyB/7XmxCgqbsWQUs=" } } diff --git a/packages/ui/dist/contracts/form-builder.json b/packages/ui/dist/contracts/form-builder.json index fde432981..94f8ba5b8 100644 --- a/packages/ui/dist/contracts/form-builder.json +++ b/packages/ui/dist/contracts/form-builder.json @@ -882,6 +882,6 @@ "copy": { "directory": "copy/form-builder/", "manifest": "copy/form-builder/manifest.json", - "digest": "sha256-a5DKdlqeMfmBODkbOZ2FKf/u4r5l4abtTYd4wZ5w9vY=" + "digest": "sha256-Nc30zX+hmCj/+Axho81JjVGR9rs0F9WjUl5R9k9GjWk=" } } diff --git a/packages/ui/dist/contracts/i3-window-frame.json b/packages/ui/dist/contracts/i3-window-frame.json index 0be9bcd7c..ede09dc2e 100644 --- a/packages/ui/dist/contracts/i3-window-frame.json +++ b/packages/ui/dist/contracts/i3-window-frame.json @@ -945,6 +945,6 @@ "copy": { "directory": "copy/i3-window-frame/", "manifest": "copy/i3-window-frame/manifest.json", - "digest": "sha256-NCADJPP+EWUI8DZnW9R3SkOJAG8+IaNI0Y87CUVua5o=" + "digest": "sha256-XQqsgeYYQ9LXW/gihUnf4A3BL00Udvz3KBTba8gbTqA=" } } diff --git a/packages/ui/dist/contracts/icon-button.json b/packages/ui/dist/contracts/icon-button.json index 79d41d901..b8294a687 100644 --- a/packages/ui/dist/contracts/icon-button.json +++ b/packages/ui/dist/contracts/icon-button.json @@ -356,6 +356,6 @@ "copy": { "directory": "copy/icon-button/", "manifest": "copy/icon-button/manifest.json", - "digest": "sha256-2xkFEJzgTFx4dNWThkOC1wrAi8DrqXB1N6TFj7VJ0Qs=" + "digest": "sha256-vFMZfyom6J5jKe5u37mHDrjUk7IocatZaJ0FZFF9eco=" } } diff --git a/packages/ui/dist/contracts/kbd.json b/packages/ui/dist/contracts/kbd.json index d67c8837a..f2596b787 100644 --- a/packages/ui/dist/contracts/kbd.json +++ b/packages/ui/dist/contracts/kbd.json @@ -261,6 +261,6 @@ "copy": { "directory": "copy/kbd/", "manifest": "copy/kbd/manifest.json", - "digest": "sha256-I1PrxYTqlOTc/bjc9Cqz3tX3S9MkTOKiKZfDj6GaoMU=" + "digest": "sha256-zOCgbqlUAgYUqZiflWUJN8D3iREdCbe2uSNY7LTUVXc=" } } diff --git a/packages/ui/dist/contracts/link.json b/packages/ui/dist/contracts/link.json index f30d6fc1f..51019dffc 100644 --- a/packages/ui/dist/contracts/link.json +++ b/packages/ui/dist/contracts/link.json @@ -322,6 +322,6 @@ "copy": { "directory": "copy/link/", "manifest": "copy/link/manifest.json", - "digest": "sha256-oTafIE+IAViI0oHnUU2yc+nCoe21J1ceIY04WDL80cE=" + "digest": "sha256-YmGKhqI/aDiKuv7KQV05qIOTAOfLCF/v+TkfJI/zcCA=" } } diff --git a/packages/ui/dist/contracts/list.json b/packages/ui/dist/contracts/list.json index 87c4c5d14..9d39a15dd 100644 --- a/packages/ui/dist/contracts/list.json +++ b/packages/ui/dist/contracts/list.json @@ -394,6 +394,6 @@ "copy": { "directory": "copy/list/", "manifest": "copy/list/manifest.json", - "digest": "sha256-5oL9lUt2Rh7SnDKawm1o+76qI3BRs5D6Fv9zEInHNqs=" + "digest": "sha256-vpfcp+3Gd0lvLGq4BdepfWusi001Xfcvl4pLnGkD3wc=" } } diff --git a/packages/ui/dist/contracts/loading-indicator.json b/packages/ui/dist/contracts/loading-indicator.json index f0757b66d..91c4814b7 100644 --- a/packages/ui/dist/contracts/loading-indicator.json +++ b/packages/ui/dist/contracts/loading-indicator.json @@ -284,6 +284,6 @@ "copy": { "directory": "copy/loading-indicator/", "manifest": "copy/loading-indicator/manifest.json", - "digest": "sha256-Kt5NVgRUk7tSoXG5AttjyxsGM5maexW10LxUO1SCzVs=" + "digest": "sha256-JBPrevY3vpaQ+G/AK4+vdQVCJgAibOXNADnnP2SzatQ=" } } diff --git a/packages/ui/dist/contracts/menu.json b/packages/ui/dist/contracts/menu.json index fe320d76b..725a630a7 100644 --- a/packages/ui/dist/contracts/menu.json +++ b/packages/ui/dist/contracts/menu.json @@ -511,6 +511,6 @@ "copy": { "directory": "copy/menu/", "manifest": "copy/menu/manifest.json", - "digest": "sha256-eoVX7JW50Ns1bF3H48oMiBwHQpVujXmyHEE5ghJMW4g=" + "digest": "sha256-CNL3cvaGQXvHWBlPVha2GHckzxSzoKgCy5veNKlqiS0=" } } diff --git a/packages/ui/dist/contracts/multiselect.json b/packages/ui/dist/contracts/multiselect.json index c51f38d46..90b563f21 100644 --- a/packages/ui/dist/contracts/multiselect.json +++ b/packages/ui/dist/contracts/multiselect.json @@ -651,6 +651,6 @@ "copy": { "directory": "copy/multiselect/", "manifest": "copy/multiselect/manifest.json", - "digest": "sha256-KYY69hwFJKds9LVIYh6+0Yr3fDHw8TjMMn7maw9COdI=" + "digest": "sha256-pCT8YyVDemWPdlGMBpAYt+GweW0jaodNFNh5FyB53NE=" } } diff --git a/packages/ui/dist/contracts/number-field.json b/packages/ui/dist/contracts/number-field.json index 2e46a4c2a..1bb603002 100644 --- a/packages/ui/dist/contracts/number-field.json +++ b/packages/ui/dist/contracts/number-field.json @@ -606,6 +606,6 @@ "copy": { "directory": "copy/number-field/", "manifest": "copy/number-field/manifest.json", - "digest": "sha256-4UO59ACgoGrblshjRtY9Nx6Z3wv201gT5Yl/YrkjOIo=" + "digest": "sha256-d2tEAN3R4JL5f89dc9qeh5wT2Kpx2hJl39oTHMF9Yhs=" } } diff --git a/packages/ui/dist/contracts/pagination.json b/packages/ui/dist/contracts/pagination.json index 3a4053d4e..805550504 100644 --- a/packages/ui/dist/contracts/pagination.json +++ b/packages/ui/dist/contracts/pagination.json @@ -376,6 +376,6 @@ "copy": { "directory": "copy/pagination/", "manifest": "copy/pagination/manifest.json", - "digest": "sha256-42MfBra/mPVu0124rOIT+z4o9+cJiVEqiO4Pbd1vUAY=" + "digest": "sha256-abLoECwx+t8UmiTTJTwip77GnqDQuK0CufG+rVps5rM=" } } diff --git a/packages/ui/dist/contracts/popover.json b/packages/ui/dist/contracts/popover.json index 9d448f8e8..f2bff0d07 100644 --- a/packages/ui/dist/contracts/popover.json +++ b/packages/ui/dist/contracts/popover.json @@ -557,6 +557,6 @@ "copy": { "directory": "copy/popover/", "manifest": "copy/popover/manifest.json", - "digest": "sha256-A9pCEvDbPktVmVfH8Cn5LqMZk46CJ4TwiSO3qu8sm4E=" + "digest": "sha256-qtI7U9MQNcKuBJoWnGbTV5TN2koer6C1EJp9Vk8YHWg=" } } diff --git a/packages/ui/dist/contracts/progress.json b/packages/ui/dist/contracts/progress.json index adb0eeb85..df5445253 100644 --- a/packages/ui/dist/contracts/progress.json +++ b/packages/ui/dist/contracts/progress.json @@ -297,6 +297,6 @@ "copy": { "directory": "copy/progress/", "manifest": "copy/progress/manifest.json", - "digest": "sha256-oWk8MNOarZ1Qp5bALfpqGLmKLM8MW7sRFrV1BhxRFJY=" + "digest": "sha256-vbTBjyTT43/kBH3aGTWwenTTG+vpb/9uE3EwvrQyNH8=" } } diff --git a/packages/ui/dist/contracts/radio-group.json b/packages/ui/dist/contracts/radio-group.json index 9d90d06ef..5e3a35e8a 100644 --- a/packages/ui/dist/contracts/radio-group.json +++ b/packages/ui/dist/contracts/radio-group.json @@ -419,6 +419,6 @@ "copy": { "directory": "copy/radio-group/", "manifest": "copy/radio-group/manifest.json", - "digest": "sha256-aJ2H5pEQm+ytgIHM353fOv8WWj0EZ/2w5JjFn10rJKc=" + "digest": "sha256-Wa2jIhHL4dSop5RhJtxZbHhzpRCaXnVrnms6lj3RAJU=" } } diff --git a/packages/ui/dist/contracts/range.json b/packages/ui/dist/contracts/range.json index 1d9473c04..1008367d1 100644 --- a/packages/ui/dist/contracts/range.json +++ b/packages/ui/dist/contracts/range.json @@ -546,6 +546,6 @@ "copy": { "directory": "copy/range/", "manifest": "copy/range/manifest.json", - "digest": "sha256-wUvuK/rH0R1M9Okdows+hEZy8BKRejoj45gRMD5zIx8=" + "digest": "sha256-c4OvxZ71jQZZ5BODPEurTXAAcKqUI1t/27DhmN0l8gY=" } } diff --git a/packages/ui/dist/contracts/repeater.json b/packages/ui/dist/contracts/repeater.json index 03741142a..dd345ac7e 100644 --- a/packages/ui/dist/contracts/repeater.json +++ b/packages/ui/dist/contracts/repeater.json @@ -562,6 +562,6 @@ "copy": { "directory": "copy/repeater/", "manifest": "copy/repeater/manifest.json", - "digest": "sha256-WHPo/96QBm03LMBbG5dmCIDwDKsHFHH4485Ks5GK3Yw=" + "digest": "sha256-ddOPfDHZVO+vtT2sU0ZPXvbQtlakjuAS2w+Atm3Qsgw=" } } diff --git a/packages/ui/dist/contracts/search-field.json b/packages/ui/dist/contracts/search-field.json index c5a37d943..306cfd70e 100644 --- a/packages/ui/dist/contracts/search-field.json +++ b/packages/ui/dist/contracts/search-field.json @@ -492,6 +492,6 @@ "copy": { "directory": "copy/search-field/", "manifest": "copy/search-field/manifest.json", - "digest": "sha256-609B332CEGR2BZk/y6Wsa7ahXf1sJJK1iXbLzzNDGOc=" + "digest": "sha256-USDdkZ8ckRRJEF/SU3bRLEXGWecX2d4N4lFUQW1RTI8=" } } diff --git a/packages/ui/dist/contracts/segmented-control.json b/packages/ui/dist/contracts/segmented-control.json index df8daba3b..95cc162d2 100644 --- a/packages/ui/dist/contracts/segmented-control.json +++ b/packages/ui/dist/contracts/segmented-control.json @@ -451,6 +451,6 @@ "copy": { "directory": "copy/segmented-control/", "manifest": "copy/segmented-control/manifest.json", - "digest": "sha256-ZQNn2MS86VKyf2NasdJBqcyJh6uVyTThUKh/SeDPG28=" + "digest": "sha256-DgIl3kuSiWylQj+tMiQsBsG1qqSbA/cWM/yb/ce86/E=" } } diff --git a/packages/ui/dist/contracts/select.json b/packages/ui/dist/contracts/select.json index c8484d5f0..5273e1647 100644 --- a/packages/ui/dist/contracts/select.json +++ b/packages/ui/dist/contracts/select.json @@ -604,6 +604,6 @@ "copy": { "directory": "copy/select/", "manifest": "copy/select/manifest.json", - "digest": "sha256-jvw2jUqqMRw42q/rCfMJ1eS6/dOU257qg8Qtc/DI5OE=" + "digest": "sha256-XEWUAUggOHYqBYRi90mxbOkUw6nSflvv1BkdttlrVn4=" } } diff --git a/packages/ui/dist/contracts/settings-panel.json b/packages/ui/dist/contracts/settings-panel.json index 2cd8e16a5..9f0e54f85 100644 --- a/packages/ui/dist/contracts/settings-panel.json +++ b/packages/ui/dist/contracts/settings-panel.json @@ -821,6 +821,6 @@ "copy": { "directory": "copy/settings-panel/", "manifest": "copy/settings-panel/manifest.json", - "digest": "sha256-UqEXYpbq1ptJHggPNTUN19vUEvRV/ELMtZcfaM70e4M=" + "digest": "sha256-uu9pq63FfqBIHGu9L2UB67aS2FGsLS8VDmMAN4aCJ2c=" } } diff --git a/packages/ui/dist/contracts/sidebar-nav.json b/packages/ui/dist/contracts/sidebar-nav.json index 7f74292d5..1a7f2e385 100644 --- a/packages/ui/dist/contracts/sidebar-nav.json +++ b/packages/ui/dist/contracts/sidebar-nav.json @@ -422,6 +422,6 @@ "copy": { "directory": "copy/sidebar-nav/", "manifest": "copy/sidebar-nav/manifest.json", - "digest": "sha256-VO6xveM5OIpLar/RKZxpxOufr5wR8nQZ32JA567smyk=" + "digest": "sha256-p5ADfs5E5mPaPEcwwIweDj+AeqRSmA4k6sMHe5WZUL0=" } } diff --git a/packages/ui/dist/contracts/skeleton.json b/packages/ui/dist/contracts/skeleton.json index 63ca363ed..a54742893 100644 --- a/packages/ui/dist/contracts/skeleton.json +++ b/packages/ui/dist/contracts/skeleton.json @@ -279,6 +279,6 @@ "copy": { "directory": "copy/skeleton/", "manifest": "copy/skeleton/manifest.json", - "digest": "sha256-Ik0FL5m9q5FAvWWNRT6dgdhbRF/1wIv79I7cCsAlizQ=" + "digest": "sha256-IDhTeG5MxLv+bexFNEe2Ppr6MRfjAq2SuWpDYogVv4U=" } } diff --git a/packages/ui/dist/contracts/skip-link.json b/packages/ui/dist/contracts/skip-link.json index ae2cfca13..1f88e6515 100644 --- a/packages/ui/dist/contracts/skip-link.json +++ b/packages/ui/dist/contracts/skip-link.json @@ -281,6 +281,6 @@ "copy": { "directory": "copy/skip-link/", "manifest": "copy/skip-link/manifest.json", - "digest": "sha256-RHhopEYfYYCAIJsnNYh/snrzL4ikhKMQto16D6RM2bc=" + "digest": "sha256-uT5+48pIlyjWHblNm1mbvUOs48/t4rAkdikJ1USnBl4=" } } diff --git a/packages/ui/dist/contracts/switch.json b/packages/ui/dist/contracts/switch.json index f7a28ff77..4eeda2134 100644 --- a/packages/ui/dist/contracts/switch.json +++ b/packages/ui/dist/contracts/switch.json @@ -396,6 +396,6 @@ "copy": { "directory": "copy/switch/", "manifest": "copy/switch/manifest.json", - "digest": "sha256-9qe7Own3wU6ScYVQZPEqWsp3h4rbch44RxcFcHbty7Y=" + "digest": "sha256-KNKjAzlF7Lo8fV7B+NujiUUl+g6vKkbTeqIUqWYbtlo=" } } diff --git a/packages/ui/dist/contracts/table.json b/packages/ui/dist/contracts/table.json index 1e8a20ae2..63e3b921b 100644 --- a/packages/ui/dist/contracts/table.json +++ b/packages/ui/dist/contracts/table.json @@ -419,6 +419,6 @@ "copy": { "directory": "copy/table/", "manifest": "copy/table/manifest.json", - "digest": "sha256-tvWu57ODVYxvIxTP4E2tRSr1XXn+jCQ6wIPEYa1/jAs=" + "digest": "sha256-B6eCEQB3vn4XFs1hZA+wamnWIpSWQOrAQMcrIkoUCE0=" } } diff --git a/packages/ui/dist/contracts/tabs.json b/packages/ui/dist/contracts/tabs.json index bf09f6d78..75f987fea 100644 --- a/packages/ui/dist/contracts/tabs.json +++ b/packages/ui/dist/contracts/tabs.json @@ -395,6 +395,6 @@ "copy": { "directory": "copy/tabs/", "manifest": "copy/tabs/manifest.json", - "digest": "sha256-WclRBxvisEeduXeY0eL9756ei20T9Z1+wS2GJ1B0yx4=" + "digest": "sha256-nIGTh6QGw8FBPOIA6CmOHjxQvCZeTD4GIYKChNA+LH8=" } } diff --git a/packages/ui/dist/contracts/terminal.json b/packages/ui/dist/contracts/terminal.json index 9feba0a28..4b4860d76 100644 --- a/packages/ui/dist/contracts/terminal.json +++ b/packages/ui/dist/contracts/terminal.json @@ -527,6 +527,6 @@ "copy": { "directory": "copy/terminal/", "manifest": "copy/terminal/manifest.json", - "digest": "sha256-R6fteNdTjGjYY6RLBBUjM7wUCoxN1QCxe7DGXnqO9Yg=" + "digest": "sha256-E9cWmkLUFpaqgEbSE1Ee1XeECG37AHYy2D3MGUli1hM=" } } diff --git a/packages/ui/dist/contracts/text-field.json b/packages/ui/dist/contracts/text-field.json index 190d318aa..a1078be1b 100644 --- a/packages/ui/dist/contracts/text-field.json +++ b/packages/ui/dist/contracts/text-field.json @@ -534,6 +534,6 @@ "copy": { "directory": "copy/text-field/", "manifest": "copy/text-field/manifest.json", - "digest": "sha256-hcXV2Vi1DhJRQohjSviBXp1aXkPz9EviFqirXPNm87o=" + "digest": "sha256-j9nXR2jD4nunrrFDVZngRnTMw7V+jHlKqlWwFdYVed8=" } } diff --git a/packages/ui/dist/contracts/textarea.json b/packages/ui/dist/contracts/textarea.json index 25e4b5fae..c0b3a4d8a 100644 --- a/packages/ui/dist/contracts/textarea.json +++ b/packages/ui/dist/contracts/textarea.json @@ -490,6 +490,6 @@ "copy": { "directory": "copy/textarea/", "manifest": "copy/textarea/manifest.json", - "digest": "sha256-DyaG2k7o6BlcPa+H2TJnjk2tqWxwmqrMOE5RDZJkxBw=" + "digest": "sha256-nrds2Ehx9pEgrAOTQ/KJcaXUXxUJE8UgzxMg6MKgQXg=" } } diff --git a/packages/ui/dist/contracts/time-picker.json b/packages/ui/dist/contracts/time-picker.json index c489f7104..8c8861229 100644 --- a/packages/ui/dist/contracts/time-picker.json +++ b/packages/ui/dist/contracts/time-picker.json @@ -566,6 +566,6 @@ "copy": { "directory": "copy/time-picker/", "manifest": "copy/time-picker/manifest.json", - "digest": "sha256-/ZoFdyjtITEpXf4lTIklavQqcxnnUbhOH6lLOQ0jtt4=" + "digest": "sha256-dWGjEYZtZLRxT/qPO7RWBLUwAZeKkHO1zjPVxIOWYY0=" } } diff --git a/packages/ui/dist/contracts/timeline.json b/packages/ui/dist/contracts/timeline.json index 61b6ddcc2..d5a055cc2 100644 --- a/packages/ui/dist/contracts/timeline.json +++ b/packages/ui/dist/contracts/timeline.json @@ -279,6 +279,6 @@ "copy": { "directory": "copy/timeline/", "manifest": "copy/timeline/manifest.json", - "digest": "sha256-uEJM2Pc5hRmaR+PpqU3brCfP2aRC/fB3Itfx59Sa2Q0=" + "digest": "sha256-kkfJcn0e6R43oL/tjd9hRcF7872A/kCBClELBLWrJVQ=" } } diff --git a/packages/ui/dist/contracts/toast.json b/packages/ui/dist/contracts/toast.json index 1d8c4b76e..970e1d1be 100644 --- a/packages/ui/dist/contracts/toast.json +++ b/packages/ui/dist/contracts/toast.json @@ -523,6 +523,6 @@ "copy": { "directory": "copy/toast/", "manifest": "copy/toast/manifest.json", - "digest": "sha256-nCmjWTAM9/Z9YpPdGU7WkaZ/5fph4teBlZgYWtPLSyk=" + "digest": "sha256-oRSezqXzG8G2CO7SOE3gB8WFwPsFCgto2clZFaszucA=" } } diff --git a/packages/ui/dist/contracts/toolbar.json b/packages/ui/dist/contracts/toolbar.json index b21b735e2..5524cdc9c 100644 --- a/packages/ui/dist/contracts/toolbar.json +++ b/packages/ui/dist/contracts/toolbar.json @@ -509,6 +509,6 @@ "copy": { "directory": "copy/toolbar/", "manifest": "copy/toolbar/manifest.json", - "digest": "sha256-PwYY01GF5N9/s9FdXsJtMVY6WsdNtZLfui+KNtnqQdM=" + "digest": "sha256-Xg44V9lbRGNYlSs23Ub7Ihw+m6Mi7pgdqp5SfpGomzU=" } } diff --git a/packages/ui/dist/contracts/tooltip.json b/packages/ui/dist/contracts/tooltip.json index d14a77e5f..26977fe3e 100644 --- a/packages/ui/dist/contracts/tooltip.json +++ b/packages/ui/dist/contracts/tooltip.json @@ -353,6 +353,6 @@ "copy": { "directory": "copy/tooltip/", "manifest": "copy/tooltip/manifest.json", - "digest": "sha256-al7ShkhIUcTTbKc7gBOvzD1mJGDtWWgkwetbgUzoZI4=" + "digest": "sha256-GgYaPJXmIXO4FHNDza+4NmU8dgYZlv7ixDUuG8GsKiU=" } } diff --git a/packages/ui/dist/contracts/tree.json b/packages/ui/dist/contracts/tree.json index 6c60649c9..d97e8c04f 100644 --- a/packages/ui/dist/contracts/tree.json +++ b/packages/ui/dist/contracts/tree.json @@ -323,6 +323,6 @@ "copy": { "directory": "copy/tree/", "manifest": "copy/tree/manifest.json", - "digest": "sha256-0GYN1Udf5ShojtuoMvLc3+3RUgiFtLW7Aao6WiS2uqg=" + "digest": "sha256-BUIBqmDTbjxpeKSKfVvw3GbB6dqlb5C3mRibn0Ao4Mc=" } } diff --git a/packages/ui/dist/contracts/wizard.json b/packages/ui/dist/contracts/wizard.json index 40e7ac315..e6ca74ed9 100644 --- a/packages/ui/dist/contracts/wizard.json +++ b/packages/ui/dist/contracts/wizard.json @@ -630,6 +630,6 @@ "copy": { "directory": "copy/wizard/", "manifest": "copy/wizard/manifest.json", - "digest": "sha256-f1tphJBiywczN6ta9PIme/jOZTIn1DL09FjKqrLgBzw=" + "digest": "sha256-Vf34na5KixdN06CY/a3gIokAxAGD9dfyNynURUGHv84=" } } diff --git a/packages/ui/dist/copy/admin-form/manifest.json b/packages/ui/dist/copy/admin-form/manifest.json index 4c1d0d170..b4e6758a6 100644 --- a/packages/ui/dist/copy/admin-form/manifest.json +++ b/packages/ui/dist/copy/admin-form/manifest.json @@ -5,31 +5,31 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/admin-form.md", "dependencies": [ "register/admin-form.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "register/text-field.js", "components/text-field.js", - "chunks/native-BjBt1sUh.js", + "chunks/native-D61761VL.js", "register/textarea.js", "components/textarea.js", "register/select.js", "components/select.js", "components/admin-form.js", - "chunks/forms-CE_hP1hg.js" + "chunks/forms-C3u5121t.js" ], "files": { - "runtime/register/admin-form.js": "sha256-3IJTJLTksVuLj5PxdfQUbymfAb+K4yKLDzOUMb+MHP0=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/register/text-field.js": "sha256-gmqyzVDUD/VCnOF5nDRA0n1F4I7q7lE02AdZeBCFrUk=", - "runtime/components/text-field.js": "sha256-4c47ee0iFW2YWW+dVR1PBSJMwOOa5rmKhJSalXzm+Zo=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", - "runtime/register/textarea.js": "sha256-OGjZrk++zzTI91HXv7chKm86kRb5xICVcoOOdMidF2g=", - "runtime/components/textarea.js": "sha256-pi3Oj4itdBVYU/EaRSZ64BqAEsBdeUH4LCG2kwSUKfw=", - "runtime/register/select.js": "sha256-TN7apnaEDR69Eobpnesx4c3Yr2iU33xNGj/q9i+nFtw=", - "runtime/components/select.js": "sha256-QSO5F4fiwtnnIHZ9/a9n62yVZRlGUIofNkw2oXYIzGY=", - "runtime/components/admin-form.js": "sha256-FVzHg1y71Fg3LptLCSedTH/NQIxijxfYfjfBaYWXGS4=", - "runtime/chunks/forms-CE_hP1hg.js": "sha256-uOnoMuSkUbm9C/GfR+PDLYCykyHOQ1Ni7g59c4YMOS0=", + "runtime/register/admin-form.js": "sha256-yYy1AQy9AAay2N03Zg4YG6XoNz4WvuslU9TQ3hVosd0=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/register/text-field.js": "sha256-MdEo5+b/G/mM5hz7fcSDyO//Htiapsit78fIYEhm59k=", + "runtime/components/text-field.js": "sha256-qPB+cDkHzpm0/dIb3MLq2aw8aYuTw8eeiXDYfuaVwwE=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", + "runtime/register/textarea.js": "sha256-kKiC3PacJzn+IIdz6JEkzMEOawMA3/ge/FCAnqsmWPM=", + "runtime/components/textarea.js": "sha256-/Z89vI8KLV9ojTcxZPRnV0C0nGRVDX3vFp0LRy/BR4M=", + "runtime/register/select.js": "sha256-a/ebYoMxXf0lulroJxRYiTUDtJLmr23xOp4f3nhwepc=", + "runtime/components/select.js": "sha256-5I3s1W7GlcelP7ffSDNZXafcFZmzILO7gFZrwhZh9Ps=", + "runtime/components/admin-form.js": "sha256-nyvONORv1EfGlW/M4O9Ee7xfMtIOTsqlYyyIWgOF+yg=", + "runtime/chunks/forms-C3u5121t.js": "sha256-DymhKeiaCcQj+DmkDxoEwP0Md4YxiSpCxyYS4eiMnV0=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-N8dnCpPJJWG/StUZN68/NzU+Ag/vEyCPsjoHNJ8SMTI=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/admin-form/runtime/chunks/choice-DqwWT5pJ.js similarity index 99% rename from packages/ui/dist/chunks/choice-B7mo5Eq3.js rename to packages/ui/dist/copy/admin-form/runtime/chunks/choice-DqwWT5pJ.js index 849c80b8b..a20d3e3f6 100644 --- a/packages/ui/dist/chunks/choice-B7mo5Eq3.js +++ b/packages/ui/dist/copy/admin-form/runtime/chunks/choice-DqwWT5pJ.js @@ -1,4 +1,4 @@ -//#region packages/ui/src/internal/dom.js +// packages/ui/src/internal/dom.js var all = (root, selector) => [...root.querySelectorAll(selector)]; var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; var visible = (node) => !node.closest("[hidden]"); @@ -88,8 +88,7 @@ function place(trigger, popup) { overflowY: "auto" }); } -//#endregion -//#region packages/ui/src/internal/temporal.js +// packages/ui/src/internal/temporal.js var instances = /* @__PURE__ */ new WeakMap(); var sequence$1 = 0; function mountTemporal(input) { @@ -518,8 +517,7 @@ function mountTemporal(input) { instances.set(input, api); return api; } -//#endregion -//#region packages/ui/src/internal/choice.js +// packages/ui/src/internal/choice.js var mounted = /* @__PURE__ */ new WeakMap(); var sequence = 0; function mountChoice(select) { @@ -934,5 +932,4 @@ function enhanceControls(root) { } }; } -//#endregion export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/admin-form/runtime/chunks/element-DcrNU9Wh.js similarity index 98% rename from packages/ui/dist/chunks/element-Dovcr9Ky.js rename to packages/ui/dist/copy/admin-form/runtime/chunks/element-DcrNU9Wh.js index aa7a67cb4..86fb43da9 100644 --- a/packages/ui/dist/chunks/element-Dovcr9Ky.js +++ b/packages/ui/dist/copy/admin-form/runtime/chunks/element-DcrNU9Wh.js @@ -1,5 +1,5 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js var HTMLElementBase = globalThis.HTMLElement ?? class {}; var nextInstance = 0; var J3w1Element = class extends HTMLElementBase { @@ -228,5 +228,4 @@ function registerElement(name, Constructor, registry = globalThis.customElements if (!current) registry.define(name, Constructor); return current ?? Constructor; } -//#endregion export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/chunks/forms-CE_hP1hg.js b/packages/ui/dist/copy/admin-form/runtime/chunks/forms-C3u5121t.js similarity index 96% rename from packages/ui/dist/chunks/forms-CE_hP1hg.js rename to packages/ui/dist/copy/admin-form/runtime/chunks/forms-C3u5121t.js index 6ad3b48f5..7eaab7c98 100644 --- a/packages/ui/dist/chunks/forms-CE_hP1hg.js +++ b/packages/ui/dist/copy/admin-form/runtime/chunks/forms-C3u5121t.js @@ -1,5 +1,5 @@ -import { i as all, l as make, o as enabled } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/forms.js +import { i as all, l as make, o as enabled } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/forms.js function wizard(root, { on }) { const panels = all(root, ".wizard-panel"), steps = all(root, ".wizard-step-button"), backButton = root.querySelector(".wizard-back"), nextButton = root.querySelector(".wizard-next"); if (!panels.length || panels.length !== steps.length) throw new Error("A wizard requires one complete panel for each step button"); @@ -119,5 +119,4 @@ function formComposition(root, { on }) { if (root.querySelector("[data-start=\"review\"]")) showReview(false); return {}; } -//#endregion export { wizard as n, formComposition as t }; diff --git a/packages/ui/dist/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/admin-form/runtime/chunks/native-D61761VL.js similarity index 98% rename from packages/ui/dist/chunks/native-BjBt1sUh.js rename to packages/ui/dist/copy/admin-form/runtime/chunks/native-D61761VL.js index 032f76c74..d73311256 100644 --- a/packages/ui/dist/chunks/native-BjBt1sUh.js +++ b/packages/ui/dist/copy/admin-form/runtime/chunks/native-D61761VL.js @@ -1,5 +1,5 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js function content() { return {}; } @@ -285,5 +285,4 @@ function fileInput(root, { on, signal }) { attributeChanged: draw }; } -//#endregion export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/admin-form/runtime/components/admin-form.js b/packages/ui/dist/copy/admin-form/runtime/components/admin-form.js index f786258d5..76c220293 100644 --- a/packages/ui/dist/copy/admin-form/runtime/components/admin-form.js +++ b/packages/ui/dist/copy/admin-form/runtime/components/admin-form.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as formComposition } from "../chunks/forms-CE_hP1hg.js"; -//#region .cache/ui-build/entries/components/admin-form.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as formComposition } from "../chunks/forms-C3u5121t.js"; +// .cache/ui-build/entries/components/admin-form.js var J3w1AdminForm = class extends J3w1Element { static componentId = "admin-form"; static version = "4.0.0"; - static implementationId = "sha256-86V5kk3lZt3iA5GdiMBYc8P2mc4pO3KTo02FmkKh71k="; + static implementationId = "sha256-nRr2ehiaHW5Pojp+99nPTbxKA38KgfMFXwRXtoTEy/U="; static connect = formComposition; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1AdminForm }; diff --git a/packages/ui/dist/copy/admin-form/runtime/components/select.js b/packages/ui/dist/copy/admin-form/runtime/components/select.js index a59b0acab..5adb3c6f7 100644 --- a/packages/ui/dist/copy/admin-form/runtime/components/select.js +++ b/packages/ui/dist/copy/admin-form/runtime/components/select.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/select.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/select.js var J3w1Select = class extends J3w1Element { static componentId = "select"; static version = "4.0.0"; - static implementationId = "sha256-/4CAqDSF84DTC0pEcQUtcmmtAaVge6ifWVX3elTZzLM="; + static implementationId = "sha256-ghLIdVGffsPUo96JXVnI3p2L5ORJKK/Xdu7X3DOz4m0="; static connect = fields; static upgradeProperties = [ "disabled", @@ -39,5 +39,4 @@ var J3w1Select = class extends J3w1Element { }); } }; -//#endregion export { J3w1Select }; diff --git a/packages/ui/dist/copy/admin-form/runtime/components/text-field.js b/packages/ui/dist/copy/admin-form/runtime/components/text-field.js index 5f6946538..bfc3476ad 100644 --- a/packages/ui/dist/copy/admin-form/runtime/components/text-field.js +++ b/packages/ui/dist/copy/admin-form/runtime/components/text-field.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/text-field.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/text-field.js var J3w1TextField = class extends J3w1Element { static componentId = "text-field"; static version = "4.0.0"; - static implementationId = "sha256-k06i0LBPa/oPe2VNmxbJkBzisp1zcAENq3MeVnKZzAo="; + static implementationId = "sha256-/LAwaTyhlpYQI8437cVvaHxrflDBWGv7PN7EEfW2aSE="; static connect = fields; static upgradeProperties = [ "disabled", @@ -31,5 +31,4 @@ var J3w1TextField = class extends J3w1Element { return this._api.stepBy(...args); } }; -//#endregion export { J3w1TextField }; diff --git a/packages/ui/dist/copy/admin-form/runtime/components/textarea.js b/packages/ui/dist/copy/admin-form/runtime/components/textarea.js index 850762b41..bb600b3d9 100644 --- a/packages/ui/dist/copy/admin-form/runtime/components/textarea.js +++ b/packages/ui/dist/copy/admin-form/runtime/components/textarea.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/textarea.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/textarea.js var J3w1Textarea = class extends J3w1Element { static componentId = "textarea"; static version = "4.0.0"; - static implementationId = "sha256-BoVEmVsZUWTLPVMKc4WLoQfNpjGc4Wy8j7o7zHck1uQ="; + static implementationId = "sha256-N6gpTKdWZilxDYkj8So4jkvfInVXt3HlRRVVtkRkqsM="; static connect = fields; static upgradeProperties = [ "disabled", @@ -27,5 +27,4 @@ var J3w1Textarea = class extends J3w1Element { return this._api.clear(...args); } }; -//#endregion export { J3w1Textarea }; diff --git a/packages/ui/dist/copy/admin-form/runtime/register/admin-form.js b/packages/ui/dist/copy/admin-form/runtime/register/admin-form.js index a6ac994bb..3dccd51be 100644 --- a/packages/ui/dist/copy/admin-form/runtime/register/admin-form.js +++ b/packages/ui/dist/copy/admin-form/runtime/register/admin-form.js @@ -1,9 +1,8 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import "./text-field.js"; import "./textarea.js"; import "./select.js"; import { J3w1AdminForm } from "../components/admin-form.js"; -//#region .cache/ui-build/entries/register/admin-form.js +// .cache/ui-build/entries/register/admin-form.js var element = registerElement("j3w1-admin-form", J3w1AdminForm); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/admin-form/runtime/register/select.js b/packages/ui/dist/copy/admin-form/runtime/register/select.js index 6fcd3d855..64f3c5936 100644 --- a/packages/ui/dist/copy/admin-form/runtime/register/select.js +++ b/packages/ui/dist/copy/admin-form/runtime/register/select.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Select } from "../components/select.js"; -//#region .cache/ui-build/entries/register/select.js +// .cache/ui-build/entries/register/select.js var element = registerElement("j3w1-select", J3w1Select); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/admin-form/runtime/register/text-field.js b/packages/ui/dist/copy/admin-form/runtime/register/text-field.js index 01007e107..53e0c005f 100644 --- a/packages/ui/dist/copy/admin-form/runtime/register/text-field.js +++ b/packages/ui/dist/copy/admin-form/runtime/register/text-field.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1TextField } from "../components/text-field.js"; -//#region .cache/ui-build/entries/register/text-field.js +// .cache/ui-build/entries/register/text-field.js var element = registerElement("j3w1-text-field", J3w1TextField); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/admin-form/runtime/register/textarea.js b/packages/ui/dist/copy/admin-form/runtime/register/textarea.js index 2e9a5db69..36b7b5d3c 100644 --- a/packages/ui/dist/copy/admin-form/runtime/register/textarea.js +++ b/packages/ui/dist/copy/admin-form/runtime/register/textarea.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Textarea } from "../components/textarea.js"; -//#region .cache/ui-build/entries/register/textarea.js +// .cache/ui-build/entries/register/textarea.js var element = registerElement("j3w1-textarea", J3w1Textarea); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/alert/manifest.json b/packages/ui/dist/copy/alert/manifest.json index d5d295a25..1199899c6 100644 --- a/packages/ui/dist/copy/alert/manifest.json +++ b/packages/ui/dist/copy/alert/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/alert.md", "dependencies": [ "register/alert.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/alert.js", - "chunks/overlays-BwgpF4jI.js" + "chunks/overlays-BW66WXLm.js" ], "files": { - "runtime/register/alert.js": "sha256-tioVtq6u1i9xQuPnmdCiimbU19h1/epCn1uitDhU938=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/alert.js": "sha256-ipEjIR62L4Lq8O1vkv4IzvYM7kLeFjfhYEw6MSL03pY=", - "runtime/chunks/overlays-BwgpF4jI.js": "sha256-NAd99OT4kDsFp8IHscKRus2jY6XRsq+GMzplWbJsY4U=", + "runtime/register/alert.js": "sha256-7NCDMaMb7R+vWVYpL0Q7UOd/2hi0nNoG7b/xzw1ISwM=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/alert.js": "sha256-Ww7L88Sc1WN1nt7rRaqX4VZ6N9euzD/gg9otTIqd/24=", + "runtime/chunks/overlays-BW66WXLm.js": "sha256-Z9etmUpuDuykKbJkriLMz8iiYnOP9uMUAshKwoHc1I8=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-5Dd4DFZ5Lg+H5ZcZnWfb8Ommsp9rKKRLJYR0cpgWWpU=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/alert/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/alert/runtime/chunks/choice-DqwWT5pJ.js similarity index 99% rename from packages/ui/dist/copy/alert/runtime/chunks/choice-B7mo5Eq3.js rename to packages/ui/dist/copy/alert/runtime/chunks/choice-DqwWT5pJ.js index 849c80b8b..a20d3e3f6 100644 --- a/packages/ui/dist/copy/alert/runtime/chunks/choice-B7mo5Eq3.js +++ b/packages/ui/dist/copy/alert/runtime/chunks/choice-DqwWT5pJ.js @@ -1,4 +1,4 @@ -//#region packages/ui/src/internal/dom.js +// packages/ui/src/internal/dom.js var all = (root, selector) => [...root.querySelectorAll(selector)]; var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; var visible = (node) => !node.closest("[hidden]"); @@ -88,8 +88,7 @@ function place(trigger, popup) { overflowY: "auto" }); } -//#endregion -//#region packages/ui/src/internal/temporal.js +// packages/ui/src/internal/temporal.js var instances = /* @__PURE__ */ new WeakMap(); var sequence$1 = 0; function mountTemporal(input) { @@ -518,8 +517,7 @@ function mountTemporal(input) { instances.set(input, api); return api; } -//#endregion -//#region packages/ui/src/internal/choice.js +// packages/ui/src/internal/choice.js var mounted = /* @__PURE__ */ new WeakMap(); var sequence = 0; function mountChoice(select) { @@ -934,5 +932,4 @@ function enhanceControls(root) { } }; } -//#endregion export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/avatar/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/alert/runtime/chunks/element-DcrNU9Wh.js similarity index 98% rename from packages/ui/dist/copy/avatar/runtime/chunks/element-Dovcr9Ky.js rename to packages/ui/dist/copy/alert/runtime/chunks/element-DcrNU9Wh.js index aa7a67cb4..86fb43da9 100644 --- a/packages/ui/dist/copy/avatar/runtime/chunks/element-Dovcr9Ky.js +++ b/packages/ui/dist/copy/alert/runtime/chunks/element-DcrNU9Wh.js @@ -1,5 +1,5 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js var HTMLElementBase = globalThis.HTMLElement ?? class {}; var nextInstance = 0; var J3w1Element = class extends HTMLElementBase { @@ -228,5 +228,4 @@ function registerElement(name, Constructor, registry = globalThis.customElements if (!current) registry.define(name, Constructor); return current ?? Constructor; } -//#endregion export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/dialog/runtime/chunks/overlays-BwgpF4jI.js b/packages/ui/dist/copy/alert/runtime/chunks/overlays-BW66WXLm.js similarity index 98% rename from packages/ui/dist/copy/dialog/runtime/chunks/overlays-BwgpF4jI.js rename to packages/ui/dist/copy/alert/runtime/chunks/overlays-BW66WXLm.js index 4b8de2e8b..d05c73b46 100644 --- a/packages/ui/dist/copy/dialog/runtime/chunks/overlays-BwgpF4jI.js +++ b/packages/ui/dist/copy/alert/runtime/chunks/overlays-BW66WXLm.js @@ -1,5 +1,5 @@ -import { d as place, i as all, o as enabled, s as identify } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/overlays.js +import { d as place, i as all, o as enabled, s as identify } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/overlays.js function modal(root, { on }) { const dialog = root.querySelector("dialog"); if (!dialog) return {}; @@ -241,5 +241,4 @@ function feedback(root, { on }) { dismiss(id ? root.querySelector(`#${CSS.escape(id)}`) : root.querySelector(".toast,.alert") ?? root); } }; } -//#endregion export { tooltip as i, modal as n, popover as r, feedback as t }; diff --git a/packages/ui/dist/copy/alert/runtime/components/alert.js b/packages/ui/dist/copy/alert/runtime/components/alert.js index c434333d3..2d9691c78 100644 --- a/packages/ui/dist/copy/alert/runtime/components/alert.js +++ b/packages/ui/dist/copy/alert/runtime/components/alert.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as feedback } from "../chunks/overlays-BwgpF4jI.js"; -//#region .cache/ui-build/entries/components/alert.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as feedback } from "../chunks/overlays-BW66WXLm.js"; +// .cache/ui-build/entries/components/alert.js var J3w1Alert = class extends J3w1Element { static componentId = "alert"; static version = "4.0.0"; - static implementationId = "sha256-UxXRTp+Yf7lbD/vkY8rJ0A/kKL5Xkg9lnOEAvWcr7OA="; + static implementationId = "sha256-/VGmtLvULiNusvurQPJTqOcanOEqt+p9HsSZ3hi9Nyc="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -13,5 +13,4 @@ var J3w1Alert = class extends J3w1Element { return this._api.dismiss(...args); } }; -//#endregion export { J3w1Alert }; diff --git a/packages/ui/dist/copy/alert/runtime/register/alert.js b/packages/ui/dist/copy/alert/runtime/register/alert.js index 4398942dd..eaf0f2a76 100644 --- a/packages/ui/dist/copy/alert/runtime/register/alert.js +++ b/packages/ui/dist/copy/alert/runtime/register/alert.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Alert } from "../components/alert.js"; -//#region .cache/ui-build/entries/register/alert.js +// .cache/ui-build/entries/register/alert.js var element = registerElement("j3w1-alert", J3w1Alert); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/avatar/manifest.json b/packages/ui/dist/copy/avatar/manifest.json index c70895453..f0942e512 100644 --- a/packages/ui/dist/copy/avatar/manifest.json +++ b/packages/ui/dist/copy/avatar/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/avatar.md", "dependencies": [ "register/avatar.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/avatar.js", - "chunks/display-Jm9bAsnb.js" + "chunks/display-l54fb8vw.js" ], "files": { - "runtime/register/avatar.js": "sha256-vcm/QDMxjQTfPDcJ7Q7TIwknLisAbwTawOMwzAfjzhg=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/avatar.js": "sha256-eST4r5/Ji77KAR4qwQ+HUIyQL67gllpCSiBqpODqeW4=", - "runtime/chunks/display-Jm9bAsnb.js": "sha256-qZb1g04piEwY3lfFJwMe+0mXR218ljtVi8mepWxrFv8=", + "runtime/register/avatar.js": "sha256-ceYN69xE5V6HfLxlvtDkJ8xjTb80vCJ5ICs/XsmR/2c=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/avatar.js": "sha256-HKb7J6bzaF/F3ze8C/vzB6L9eaHLCswImQNP+dAE9dM=", + "runtime/chunks/display-l54fb8vw.js": "sha256-xfzo614uMLlSbZc5l+o4vHvrL8yBjQAcV/HJdmPUJ/g=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-5uftL4p30t4ItPscyYR/4jS31cRz/VU0Ga2CL/3fjhg=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/avatar/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/avatar/runtime/chunks/choice-DqwWT5pJ.js similarity index 99% rename from packages/ui/dist/copy/avatar/runtime/chunks/choice-B7mo5Eq3.js rename to packages/ui/dist/copy/avatar/runtime/chunks/choice-DqwWT5pJ.js index 849c80b8b..a20d3e3f6 100644 --- a/packages/ui/dist/copy/avatar/runtime/chunks/choice-B7mo5Eq3.js +++ b/packages/ui/dist/copy/avatar/runtime/chunks/choice-DqwWT5pJ.js @@ -1,4 +1,4 @@ -//#region packages/ui/src/internal/dom.js +// packages/ui/src/internal/dom.js var all = (root, selector) => [...root.querySelectorAll(selector)]; var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; var visible = (node) => !node.closest("[hidden]"); @@ -88,8 +88,7 @@ function place(trigger, popup) { overflowY: "auto" }); } -//#endregion -//#region packages/ui/src/internal/temporal.js +// packages/ui/src/internal/temporal.js var instances = /* @__PURE__ */ new WeakMap(); var sequence$1 = 0; function mountTemporal(input) { @@ -518,8 +517,7 @@ function mountTemporal(input) { instances.set(input, api); return api; } -//#endregion -//#region packages/ui/src/internal/choice.js +// packages/ui/src/internal/choice.js var mounted = /* @__PURE__ */ new WeakMap(); var sequence = 0; function mountChoice(select) { @@ -934,5 +932,4 @@ function enhanceControls(root) { } }; } -//#endregion export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/code-editor/runtime/chunks/display-Jm9bAsnb.js b/packages/ui/dist/copy/avatar/runtime/chunks/display-l54fb8vw.js similarity index 98% rename from packages/ui/dist/copy/code-editor/runtime/chunks/display-Jm9bAsnb.js rename to packages/ui/dist/copy/avatar/runtime/chunks/display-l54fb8vw.js index 5bc817830..b2f57aaf2 100644 --- a/packages/ui/dist/copy/code-editor/runtime/chunks/display-Jm9bAsnb.js +++ b/packages/ui/dist/copy/avatar/runtime/chunks/display-l54fb8vw.js @@ -1,5 +1,5 @@ -import { i as all, l as make, o as enabled } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/display.js +import { i as all, l as make, o as enabled } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/display.js function avatar(root, { on }) { const frame = root.querySelector(".avatar"), fallback = root.querySelector("[data-avatar-fallback]"); if (!frame || !fallback) return {}; @@ -208,5 +208,4 @@ function developerView(root, { on }) { pre.textContent = String(text); } }; } -//#endregion export { editorSearch as i, chart as n, developerView as r, avatar as t }; diff --git a/packages/ui/dist/copy/admin-form/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/avatar/runtime/chunks/element-DcrNU9Wh.js similarity index 98% rename from packages/ui/dist/copy/admin-form/runtime/chunks/element-Dovcr9Ky.js rename to packages/ui/dist/copy/avatar/runtime/chunks/element-DcrNU9Wh.js index aa7a67cb4..86fb43da9 100644 --- a/packages/ui/dist/copy/admin-form/runtime/chunks/element-Dovcr9Ky.js +++ b/packages/ui/dist/copy/avatar/runtime/chunks/element-DcrNU9Wh.js @@ -1,5 +1,5 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js var HTMLElementBase = globalThis.HTMLElement ?? class {}; var nextInstance = 0; var J3w1Element = class extends HTMLElementBase { @@ -228,5 +228,4 @@ function registerElement(name, Constructor, registry = globalThis.customElements if (!current) registry.define(name, Constructor); return current ?? Constructor; } -//#endregion export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/avatar/runtime/components/avatar.js b/packages/ui/dist/copy/avatar/runtime/components/avatar.js index 39f8bb7e4..f7e439c41 100644 --- a/packages/ui/dist/copy/avatar/runtime/components/avatar.js +++ b/packages/ui/dist/copy/avatar/runtime/components/avatar.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as avatar } from "../chunks/display-Jm9bAsnb.js"; -//#region .cache/ui-build/entries/components/avatar.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as avatar } from "../chunks/display-l54fb8vw.js"; +// .cache/ui-build/entries/components/avatar.js var J3w1Avatar = class extends J3w1Element { static componentId = "avatar"; static version = "4.0.0"; - static implementationId = "sha256-y5w6c1MQTafVvxzhJ5TzYxwGvju264CUxS2D23RvGCQ="; + static implementationId = "sha256-h7ZI0GBRPh8k+G66StFqOp3ztZR+AceNt5+PiDohQ+M="; static connect = avatar; static upgradeProperties = [ "disabled", @@ -28,5 +28,4 @@ var J3w1Avatar = class extends J3w1Element { }); } }; -//#endregion export { J3w1Avatar }; diff --git a/packages/ui/dist/copy/avatar/runtime/register/avatar.js b/packages/ui/dist/copy/avatar/runtime/register/avatar.js index 9367113f3..1a0c3257d 100644 --- a/packages/ui/dist/copy/avatar/runtime/register/avatar.js +++ b/packages/ui/dist/copy/avatar/runtime/register/avatar.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Avatar } from "../components/avatar.js"; -//#region .cache/ui-build/entries/register/avatar.js +// .cache/ui-build/entries/register/avatar.js var element = registerElement("j3w1-avatar", J3w1Avatar); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/badge/manifest.json b/packages/ui/dist/copy/badge/manifest.json index de0bd7e60..7fe2dd7e6 100644 --- a/packages/ui/dist/copy/badge/manifest.json +++ b/packages/ui/dist/copy/badge/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/badge.md", "dependencies": [ "register/badge.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/badge.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/badge.js": "sha256-OMhgJ1tgBmSwhSWWFds0Npmgs46ZFUk4HYOnBGAntC4=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/badge.js": "sha256-7aVCilfmosfSHQDe+hY74Ms2tAC1jMlxtTExgZ+istY=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/badge.js": "sha256-56Kyt+S1p0U0oomxduPHzI9FVOdfq+QkEirj13HbH24=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/badge.js": "sha256-FlhaqGV0H9kpUnPPf0aDoS4RsvSviuRuZ2oCn+jy9kI=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-au/P4qbkjvG1QpFUYQDc35IhSbbhmFRxoXhu7zPifn8=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/badge/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/badge/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/badge/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/badge/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/badge/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/badge/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/badge/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/badge/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/badge/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/badge/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/badge/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/badge/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/button-group/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/badge/runtime/chunks/native-D61761VL.js similarity index 98% rename from packages/ui/dist/copy/button-group/runtime/chunks/native-BjBt1sUh.js rename to packages/ui/dist/copy/badge/runtime/chunks/native-D61761VL.js index 032f76c74..d73311256 100644 --- a/packages/ui/dist/copy/button-group/runtime/chunks/native-BjBt1sUh.js +++ b/packages/ui/dist/copy/badge/runtime/chunks/native-D61761VL.js @@ -1,5 +1,5 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js function content() { return {}; } @@ -285,5 +285,4 @@ function fileInput(root, { on, signal }) { attributeChanged: draw }; } -//#endregion export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/badge/runtime/components/badge.js b/packages/ui/dist/copy/badge/runtime/components/badge.js index 640dfde53..1f3ff68a1 100644 --- a/packages/ui/dist/copy/badge/runtime/components/badge.js +++ b/packages/ui/dist/copy/badge/runtime/components/badge.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/badge.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/badge.js var J3w1Badge = class extends J3w1Element { static componentId = "badge"; static version = "4.0.0"; - static implementationId = "sha256-4j+faVdrUDtcCc6a5/1Y+y9U30DXfpq/Frm/Z0bO1i8="; + static implementationId = "sha256-UhaZtelaZOVA7hb0+yXsIb0PG9ooJXYf9c759KHeA9c="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Badge }; diff --git a/packages/ui/dist/copy/badge/runtime/register/badge.js b/packages/ui/dist/copy/badge/runtime/register/badge.js index 2fe7fff68..574a2903e 100644 --- a/packages/ui/dist/copy/badge/runtime/register/badge.js +++ b/packages/ui/dist/copy/badge/runtime/register/badge.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Badge } from "../components/badge.js"; -//#region .cache/ui-build/entries/register/badge.js +// .cache/ui-build/entries/register/badge.js var element = registerElement("j3w1-badge", J3w1Badge); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/breadcrumbs/manifest.json b/packages/ui/dist/copy/breadcrumbs/manifest.json index 018188344..82dc52e8e 100644 --- a/packages/ui/dist/copy/breadcrumbs/manifest.json +++ b/packages/ui/dist/copy/breadcrumbs/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/breadcrumbs.md", "dependencies": [ "register/breadcrumbs.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/breadcrumbs.js", - "chunks/navigation-BfNzDYZB.js" + "chunks/navigation-CknoksQ5.js" ], "files": { - "runtime/register/breadcrumbs.js": "sha256-TBQ50OLAdUaAgno93QicDrgSoW5MfLyWLXoR+GWyw0M=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/breadcrumbs.js": "sha256-DgJ8uy8nkN1QOm3/zq3cYvs7xmhXCyPkXdhu3CDEE00=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", + "runtime/register/breadcrumbs.js": "sha256-T+4ZMhNyFraW/V5E84ueE/5MWurZ2UfOdAkMEh8DVa0=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/breadcrumbs.js": "sha256-lttQVA0QJicYwLEjh9+fV4T6Bbz1HugXAzgrH1lYDuw=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-+Zc2EEKW9OfZl8s+wFiHlzjJHlyVTyGwZDbPlyRKx4A=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/breadcrumbs/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/breadcrumbs/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/breadcrumbs/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/breadcrumbs/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/breadcrumbs/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/breadcrumbs/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/breadcrumbs/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/breadcrumbs/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/breadcrumbs/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/breadcrumbs/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/breadcrumbs/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/breadcrumbs/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/breadcrumbs/runtime/chunks/navigation-BfNzDYZB.js b/packages/ui/dist/copy/breadcrumbs/runtime/chunks/navigation-CknoksQ5.js similarity index 99% rename from packages/ui/dist/copy/breadcrumbs/runtime/chunks/navigation-BfNzDYZB.js rename to packages/ui/dist/copy/breadcrumbs/runtime/chunks/navigation-CknoksQ5.js index db2779553..dfd1883e6 100644 --- a/packages/ui/dist/copy/breadcrumbs/runtime/chunks/navigation-BfNzDYZB.js +++ b/packages/ui/dist/copy/breadcrumbs/runtime/chunks/navigation-CknoksQ5.js @@ -1,5 +1,5 @@ -import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/navigation.js +import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/navigation.js function tabs(root, { on }, listOverride) { const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); if (!list) return {}; @@ -373,5 +373,4 @@ function menu(root, { on }) { } }; } -//#endregion export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/breadcrumbs/runtime/components/breadcrumbs.js b/packages/ui/dist/copy/breadcrumbs/runtime/components/breadcrumbs.js index 5ce93d88b..f90b820a6 100644 --- a/packages/ui/dist/copy/breadcrumbs/runtime/components/breadcrumbs.js +++ b/packages/ui/dist/copy/breadcrumbs/runtime/components/breadcrumbs.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as disclosure } from "../chunks/navigation-BfNzDYZB.js"; -//#region .cache/ui-build/entries/components/breadcrumbs.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as disclosure } from "../chunks/navigation-CknoksQ5.js"; +// .cache/ui-build/entries/components/breadcrumbs.js var J3w1Breadcrumbs = class extends J3w1Element { static componentId = "breadcrumbs"; static version = "4.0.0"; - static implementationId = "sha256-9uiBLPIbEVI200s39xDO7x0K09v+wPg5xcoMI5B5TbY="; + static implementationId = "sha256-UzuPAevxgWxvLwLS5TgOGWH3gWcdZo9B3pvbMu/55Yc="; static connect = disclosure; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Breadcrumbs }; diff --git a/packages/ui/dist/copy/breadcrumbs/runtime/register/breadcrumbs.js b/packages/ui/dist/copy/breadcrumbs/runtime/register/breadcrumbs.js index 1b41f187d..2f3205758 100644 --- a/packages/ui/dist/copy/breadcrumbs/runtime/register/breadcrumbs.js +++ b/packages/ui/dist/copy/breadcrumbs/runtime/register/breadcrumbs.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Breadcrumbs } from "../components/breadcrumbs.js"; -//#region .cache/ui-build/entries/register/breadcrumbs.js +// .cache/ui-build/entries/register/breadcrumbs.js var element = registerElement("j3w1-breadcrumbs", J3w1Breadcrumbs); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/button-group/manifest.json b/packages/ui/dist/copy/button-group/manifest.json index de4c4f019..266ae3516 100644 --- a/packages/ui/dist/copy/button-group/manifest.json +++ b/packages/ui/dist/copy/button-group/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/button-group.md", "dependencies": [ "register/button-group.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/button-group.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/button-group.js": "sha256-n7o1qzR7ijgCLKarzz6j0E+PWPYtlemBEaNgIZwu2R4=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/button-group.js": "sha256-aYOeTtqsQuXqHLxIh17+FGxd0WuETY31YqUOFh32A4A=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/button-group.js": "sha256-CFMDZp4J0G3eNpyzz9h6e411fRQd4qCFeWFwo78IXAM=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/button-group.js": "sha256-03J38xNN25EiiWRaSOx/ndOebdEU8ay5ANw68TOo1sc=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-0HQ2nfSUmtlZV8Bwsob1wBnVODkxbeI16OqeME3hc2M=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/button-group/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/button-group/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/button-group/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/button-group/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/button-group/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/button-group/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/button-group/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/button-group/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/button-group/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/button-group/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/button-group/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/button-group/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/admin-form/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/button-group/runtime/chunks/native-D61761VL.js similarity index 98% rename from packages/ui/dist/copy/admin-form/runtime/chunks/native-BjBt1sUh.js rename to packages/ui/dist/copy/button-group/runtime/chunks/native-D61761VL.js index 032f76c74..d73311256 100644 --- a/packages/ui/dist/copy/admin-form/runtime/chunks/native-BjBt1sUh.js +++ b/packages/ui/dist/copy/button-group/runtime/chunks/native-D61761VL.js @@ -1,5 +1,5 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js function content() { return {}; } @@ -285,5 +285,4 @@ function fileInput(root, { on, signal }) { attributeChanged: draw }; } -//#endregion export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/button-group/runtime/components/button-group.js b/packages/ui/dist/copy/button-group/runtime/components/button-group.js index e5443b0f9..bf93a804c 100644 --- a/packages/ui/dist/copy/button-group/runtime/components/button-group.js +++ b/packages/ui/dist/copy/button-group/runtime/components/button-group.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as actions } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/button-group.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as actions } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/button-group.js var J3w1ButtonGroup = class extends J3w1Element { static componentId = "button-group"; static version = "4.0.0"; - static implementationId = "sha256-QC6YHzPpUytpyeDknjyX9Ke/akglG1NzBtJnCYjqgaA="; + static implementationId = "sha256-nnr9B7SyHVj5bc9rHfUyedaHq9k8ZhIaf8pJalBfpeU="; static connect = actions; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...[ @@ -13,5 +13,4 @@ var J3w1ButtonGroup = class extends J3w1Element { "tone" ]]; }; -//#endregion export { J3w1ButtonGroup }; diff --git a/packages/ui/dist/copy/button-group/runtime/register/button-group.js b/packages/ui/dist/copy/button-group/runtime/register/button-group.js index 86bb9c765..48b52b1c6 100644 --- a/packages/ui/dist/copy/button-group/runtime/register/button-group.js +++ b/packages/ui/dist/copy/button-group/runtime/register/button-group.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1ButtonGroup } from "../components/button-group.js"; -//#region .cache/ui-build/entries/register/button-group.js +// .cache/ui-build/entries/register/button-group.js var element = registerElement("j3w1-button-group", J3w1ButtonGroup); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/button/manifest.json b/packages/ui/dist/copy/button/manifest.json index 600b3806d..794b2f4af 100644 --- a/packages/ui/dist/copy/button/manifest.json +++ b/packages/ui/dist/copy/button/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/button.md", "dependencies": [ "register/button.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/button.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/button.js": "sha256-HvNFbu03EVUxXcYT4la11XNeC522dyJdNi3USEnMuL0=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/button.js": "sha256-csyoBHNGYp8/JTgXnOjZuGEFG9u6KytBLHY3MtJdxcs=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/button.js": "sha256-xBHeJlZwrTjeg7JzsVRbjiBe9MekpRJR+0ALoHB3Lhk=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/button.js": "sha256-AUGeIp5H3ziJjknDX7a+AGZ3l56vccuGARDQe1NEJ5o=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-3CHgfHOT+xBve253iRY/PvSWDiyrTR4uMxiCy2jC7OQ=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/button/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/button/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/button/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/button/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/button/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/button/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/button/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/button/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/button/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/button/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/button/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/button/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/button/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/button/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/button/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/button/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/button/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/button/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/button/runtime/components/button.js b/packages/ui/dist/copy/button/runtime/components/button.js index 3dfd4d373..fb03b5228 100644 --- a/packages/ui/dist/copy/button/runtime/components/button.js +++ b/packages/ui/dist/copy/button/runtime/components/button.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as actions } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/button.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as actions } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/button.js var J3w1Button = class extends J3w1Element { static componentId = "button"; static version = "4.0.0"; - static implementationId = "sha256-5XqIG0jRl2EIptqWgZIiuSKdNf0pHpMOZB14A1W3DqU="; + static implementationId = "sha256-koXqbIz5v3u05mvNMvJSSn5/vohXTinBFDR/EEkjLc0="; static connect = actions; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...[ @@ -13,5 +13,4 @@ var J3w1Button = class extends J3w1Element { "tone" ]]; }; -//#endregion export { J3w1Button }; diff --git a/packages/ui/dist/copy/button/runtime/register/button.js b/packages/ui/dist/copy/button/runtime/register/button.js index b01aa4dae..bc7ea515c 100644 --- a/packages/ui/dist/copy/button/runtime/register/button.js +++ b/packages/ui/dist/copy/button/runtime/register/button.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Button } from "../components/button.js"; -//#region .cache/ui-build/entries/register/button.js +// .cache/ui-build/entries/register/button.js var element = registerElement("j3w1-button", J3w1Button); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/card/manifest.json b/packages/ui/dist/copy/card/manifest.json index ebdfe2e83..28de3bd85 100644 --- a/packages/ui/dist/copy/card/manifest.json +++ b/packages/ui/dist/copy/card/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/card.md", "dependencies": [ "register/card.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/card.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/card.js": "sha256-4IdkxATA99m7+u4hZzbgLzxNtZyQcI8WI8kkDxErCxI=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/card.js": "sha256-CE1Pt81XkHCmaZj7t3LqXTUnuvHd4E3/Od5t2v07ltA=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/card.js": "sha256-zMiNbkc2DBlaA01E05Odaecz1JA1cOewK1N8Z3aANew=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/card.js": "sha256-+1yNt41KPhmbGI3BqDj0s6zM8B6TeVyfUnzwt+kiAPA=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-FIugfi7dJgtnME2RJdIYZUQl/3O/WVR1fu23onC7U/M=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/card/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/card/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/card/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/card/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/card/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/card/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/card/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/card/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/card/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/card/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/card/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/card/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/card/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/card/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/card/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/card/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/card/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/card/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/card/runtime/components/card.js b/packages/ui/dist/copy/card/runtime/components/card.js index 9981d665b..4b88cfed7 100644 --- a/packages/ui/dist/copy/card/runtime/components/card.js +++ b/packages/ui/dist/copy/card/runtime/components/card.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/card.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/card.js var J3w1Card = class extends J3w1Element { static componentId = "card"; static version = "4.0.0"; - static implementationId = "sha256-1zEhR7grQaSCkJEXxbq66aFLUPYuFPcwf/JnBD3tNdQ="; + static implementationId = "sha256-+1RpGzq4cNP4XbkcRsKDIZ47NkRYjt3g6rAyL67eKAg="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Card }; diff --git a/packages/ui/dist/copy/card/runtime/register/card.js b/packages/ui/dist/copy/card/runtime/register/card.js index 2a9535cee..2fd6ddbba 100644 --- a/packages/ui/dist/copy/card/runtime/register/card.js +++ b/packages/ui/dist/copy/card/runtime/register/card.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Card } from "../components/card.js"; -//#region .cache/ui-build/entries/register/card.js +// .cache/ui-build/entries/register/card.js var element = registerElement("j3w1-card", J3w1Card); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/chart/manifest.json b/packages/ui/dist/copy/chart/manifest.json index 61fd09f98..af592b520 100644 --- a/packages/ui/dist/copy/chart/manifest.json +++ b/packages/ui/dist/copy/chart/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/chart.md", "dependencies": [ "register/chart.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/chart.js", - "chunks/display-Jm9bAsnb.js" + "chunks/display-l54fb8vw.js" ], "files": { - "runtime/register/chart.js": "sha256-T98hQYpUxEQ3kRDeztnuOxP5XmwfddBBocBZ3rdTxT8=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/chart.js": "sha256-hVyc1MgrIwRQZWPz61YJX6ScFRhDJTjMKtYEs5Xtxoo=", - "runtime/chunks/display-Jm9bAsnb.js": "sha256-qZb1g04piEwY3lfFJwMe+0mXR218ljtVi8mepWxrFv8=", + "runtime/register/chart.js": "sha256-andwTROOZAuydVX/8AHv1ch78Vp2Bpfw0e1QhJuc1H8=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/chart.js": "sha256-b+gmdldG475mc83KqS69DHLQ3yWt0OTgOk+UNqB5J9o=", + "runtime/chunks/display-l54fb8vw.js": "sha256-xfzo614uMLlSbZc5l+o4vHvrL8yBjQAcV/HJdmPUJ/g=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-bZANhpWKREr2mT2bkDhKqg7tacAvTsBxyTk7F9aojeE=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/chart/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/chart/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/chart/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/chart/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/chart/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/chart/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/avatar/runtime/chunks/display-Jm9bAsnb.js b/packages/ui/dist/copy/chart/runtime/chunks/display-l54fb8vw.js similarity index 98% rename from packages/ui/dist/copy/avatar/runtime/chunks/display-Jm9bAsnb.js rename to packages/ui/dist/copy/chart/runtime/chunks/display-l54fb8vw.js index 5bc817830..b2f57aaf2 100644 --- a/packages/ui/dist/copy/avatar/runtime/chunks/display-Jm9bAsnb.js +++ b/packages/ui/dist/copy/chart/runtime/chunks/display-l54fb8vw.js @@ -1,5 +1,5 @@ -import { i as all, l as make, o as enabled } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/display.js +import { i as all, l as make, o as enabled } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/display.js function avatar(root, { on }) { const frame = root.querySelector(".avatar"), fallback = root.querySelector("[data-avatar-fallback]"); if (!frame || !fallback) return {}; @@ -208,5 +208,4 @@ function developerView(root, { on }) { pre.textContent = String(text); } }; } -//#endregion export { editorSearch as i, chart as n, developerView as r, avatar as t }; diff --git a/packages/ui/dist/copy/chart/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/chart/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/chart/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/chart/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/chart/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/chart/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/chart/runtime/components/chart.js b/packages/ui/dist/copy/chart/runtime/components/chart.js index 70d90b671..1be85f8ea 100644 --- a/packages/ui/dist/copy/chart/runtime/components/chart.js +++ b/packages/ui/dist/copy/chart/runtime/components/chart.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as chart } from "../chunks/display-Jm9bAsnb.js"; -//#region .cache/ui-build/entries/components/chart.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as chart } from "../chunks/display-l54fb8vw.js"; +// .cache/ui-build/entries/components/chart.js var J3w1Chart = class extends J3w1Element { static componentId = "chart"; static version = "4.0.0"; - static implementationId = "sha256-48dT14XNNF9ZyV4PB4oLs8zT/lNQqNt9rXZCl9gUYVc="; + static implementationId = "sha256-PhBwyLjFdcq2bXYtZewk49w7vPNGTKA3c6iz1WayLys="; static connect = chart; static upgradeProperties = [ "disabled", @@ -24,5 +24,4 @@ var J3w1Chart = class extends J3w1Element { }); } }; -//#endregion export { J3w1Chart }; diff --git a/packages/ui/dist/copy/chart/runtime/register/chart.js b/packages/ui/dist/copy/chart/runtime/register/chart.js index 8efbe0a3f..e1c79eef1 100644 --- a/packages/ui/dist/copy/chart/runtime/register/chart.js +++ b/packages/ui/dist/copy/chart/runtime/register/chart.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Chart } from "../components/chart.js"; -//#region .cache/ui-build/entries/register/chart.js +// .cache/ui-build/entries/register/chart.js var element = registerElement("j3w1-chart", J3w1Chart); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/checkbox/manifest.json b/packages/ui/dist/copy/checkbox/manifest.json index e0d579e5d..60023e74f 100644 --- a/packages/ui/dist/copy/checkbox/manifest.json +++ b/packages/ui/dist/copy/checkbox/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/checkbox.md", "dependencies": [ "register/checkbox.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/checkbox.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/checkbox.js": "sha256-QlNtS75LVxO+OKEWX5af518TWUVOwH5nVS8bKid/E+Y=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/checkbox.js": "sha256-M4ffC3UZvNt1LaayV7iUubw0dG33RiqLTYcb05lK3N4=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/checkbox.js": "sha256-4FXUPwf4ix3wwVjE+fGDDGgVp+oXhoxuin7qwnMqYYY=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/checkbox.js": "sha256-wYmcBKQmc0+hPiMjdLSxHFSci1qcX0h7DyRtiOtB62o=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-UbNMFdu+HW8ujyQExwYwdN9wZDBkKRrgWyLfrTITwec=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/checkbox/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/checkbox/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/checkbox/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/checkbox/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/checkbox/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/checkbox/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/checkbox/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/checkbox/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/checkbox/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/checkbox/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/checkbox/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/checkbox/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/checkbox/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/checkbox/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/checkbox/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/checkbox/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/checkbox/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/checkbox/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/checkbox/runtime/components/checkbox.js b/packages/ui/dist/copy/checkbox/runtime/components/checkbox.js index 8d7e19060..61ae79b4f 100644 --- a/packages/ui/dist/copy/checkbox/runtime/components/checkbox.js +++ b/packages/ui/dist/copy/checkbox/runtime/components/checkbox.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/checkbox.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/checkbox.js var J3w1Checkbox = class extends J3w1Element { static componentId = "checkbox"; static version = "4.0.0"; - static implementationId = "sha256-Izbz5fVyhrSfF5rLvCHcElWnQgwhYuvOSm5StKMlqUg="; + static implementationId = "sha256-qZohpwxrLq3iJ7JFmE0EmXgp3pJGmBpalNJzpOSs2jQ="; static connect = fields; static upgradeProperties = [ "disabled", @@ -51,5 +51,4 @@ var J3w1Checkbox = class extends J3w1Element { }); } }; -//#endregion export { J3w1Checkbox }; diff --git a/packages/ui/dist/copy/checkbox/runtime/register/checkbox.js b/packages/ui/dist/copy/checkbox/runtime/register/checkbox.js index 70632e2d0..c03d18e2e 100644 --- a/packages/ui/dist/copy/checkbox/runtime/register/checkbox.js +++ b/packages/ui/dist/copy/checkbox/runtime/register/checkbox.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Checkbox } from "../components/checkbox.js"; -//#region .cache/ui-build/entries/register/checkbox.js +// .cache/ui-build/entries/register/checkbox.js var element = registerElement("j3w1-checkbox", J3w1Checkbox); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/chip/manifest.json b/packages/ui/dist/copy/chip/manifest.json index 0dea881b3..4fb02a1f6 100644 --- a/packages/ui/dist/copy/chip/manifest.json +++ b/packages/ui/dist/copy/chip/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/chip.md", "dependencies": [ "register/chip.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/chip.js", - "chunks/overlays-BwgpF4jI.js" + "chunks/overlays-BW66WXLm.js" ], "files": { - "runtime/register/chip.js": "sha256-H45do+W8XNxsOyAgO7vOSM4Wm6HfTun0JETK6F/YGRo=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/chip.js": "sha256-S45gQt3C5/jkmBzAtETNlZkOIiP4jPQEUcJa7TAulk8=", - "runtime/chunks/overlays-BwgpF4jI.js": "sha256-NAd99OT4kDsFp8IHscKRus2jY6XRsq+GMzplWbJsY4U=", + "runtime/register/chip.js": "sha256-eF+2aWon9lf3LkH7QaQCkxFOzWUMmNMVKWA7fqgj2+4=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/chip.js": "sha256-MJ64P3LJsDD8m48qHWKCQnD9uybijjnCWkqC25A3ElI=", + "runtime/chunks/overlays-BW66WXLm.js": "sha256-Z9etmUpuDuykKbJkriLMz8iiYnOP9uMUAshKwoHc1I8=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-358eNya4c7h47XJC5dFUZncxpjkl0B9HRfRfxwVS8so=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/chip/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/chip/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/chip/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/chip/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/chip/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/chip/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/chip/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/chip/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/chip/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/chip/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/chip/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/chip/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/alert/runtime/chunks/overlays-BwgpF4jI.js b/packages/ui/dist/copy/chip/runtime/chunks/overlays-BW66WXLm.js similarity index 98% rename from packages/ui/dist/copy/alert/runtime/chunks/overlays-BwgpF4jI.js rename to packages/ui/dist/copy/chip/runtime/chunks/overlays-BW66WXLm.js index 4b8de2e8b..d05c73b46 100644 --- a/packages/ui/dist/copy/alert/runtime/chunks/overlays-BwgpF4jI.js +++ b/packages/ui/dist/copy/chip/runtime/chunks/overlays-BW66WXLm.js @@ -1,5 +1,5 @@ -import { d as place, i as all, o as enabled, s as identify } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/overlays.js +import { d as place, i as all, o as enabled, s as identify } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/overlays.js function modal(root, { on }) { const dialog = root.querySelector("dialog"); if (!dialog) return {}; @@ -241,5 +241,4 @@ function feedback(root, { on }) { dismiss(id ? root.querySelector(`#${CSS.escape(id)}`) : root.querySelector(".toast,.alert") ?? root); } }; } -//#endregion export { tooltip as i, modal as n, popover as r, feedback as t }; diff --git a/packages/ui/dist/copy/chip/runtime/components/chip.js b/packages/ui/dist/copy/chip/runtime/components/chip.js index e336b104c..3472b46ae 100644 --- a/packages/ui/dist/copy/chip/runtime/components/chip.js +++ b/packages/ui/dist/copy/chip/runtime/components/chip.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as feedback } from "../chunks/overlays-BwgpF4jI.js"; -//#region .cache/ui-build/entries/components/chip.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as feedback } from "../chunks/overlays-BW66WXLm.js"; +// .cache/ui-build/entries/components/chip.js var J3w1Chip = class extends J3w1Element { static componentId = "chip"; static version = "4.0.0"; - static implementationId = "sha256-LX8QtUNQgNJe9t+ID6Q+WinGVj68ZHfs0KLKk56qrpw="; + static implementationId = "sha256-BLhSWnVQYmMbTVx4pg3l9BbJVSN1kJ3PAmOAsCu7880="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -13,5 +13,4 @@ var J3w1Chip = class extends J3w1Element { return this._api.dismiss(...args); } }; -//#endregion export { J3w1Chip }; diff --git a/packages/ui/dist/copy/chip/runtime/register/chip.js b/packages/ui/dist/copy/chip/runtime/register/chip.js index d6b89d151..bdd9120bd 100644 --- a/packages/ui/dist/copy/chip/runtime/register/chip.js +++ b/packages/ui/dist/copy/chip/runtime/register/chip.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Chip } from "../components/chip.js"; -//#region .cache/ui-build/entries/register/chip.js +// .cache/ui-build/entries/register/chip.js var element = registerElement("j3w1-chip", J3w1Chip); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/code-editor/manifest.json b/packages/ui/dist/copy/code-editor/manifest.json index 32bff7086..9c5a70a73 100644 --- a/packages/ui/dist/copy/code-editor/manifest.json +++ b/packages/ui/dist/copy/code-editor/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/code-editor.md", "dependencies": [ "register/code-editor.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/code-editor.js", - "chunks/display-Jm9bAsnb.js" + "chunks/display-l54fb8vw.js" ], "files": { - "runtime/register/code-editor.js": "sha256-qnN0iH+h4BDWCcc4Q3/6f1t7opIG5ze5nI1wsQL/tDg=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/code-editor.js": "sha256-MMz8rm+dJT4XahXmR9ftmU0IhNW1NqLIHW7U3STXDPQ=", - "runtime/chunks/display-Jm9bAsnb.js": "sha256-qZb1g04piEwY3lfFJwMe+0mXR218ljtVi8mepWxrFv8=", + "runtime/register/code-editor.js": "sha256-UdHVDO1voHkuJxvk2L6GqXlhe33V2vQjMWxXPn1khuw=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/code-editor.js": "sha256-cSXmUpi0vGMqGobq9++3IbvncnACcWtOqxek0flaVgs=", + "runtime/chunks/display-l54fb8vw.js": "sha256-xfzo614uMLlSbZc5l+o4vHvrL8yBjQAcV/HJdmPUJ/g=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-aa9zAzIlna+IPd+Xivi0WU385o/+RmhG5pRVR1vsE64=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/code-editor/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/code-editor/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/code-editor/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/code-editor/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/code-editor/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/code-editor/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/chunks/display-Jm9bAsnb.js b/packages/ui/dist/copy/code-editor/runtime/chunks/display-l54fb8vw.js similarity index 98% rename from packages/ui/dist/chunks/display-Jm9bAsnb.js rename to packages/ui/dist/copy/code-editor/runtime/chunks/display-l54fb8vw.js index 5bc817830..b2f57aaf2 100644 --- a/packages/ui/dist/chunks/display-Jm9bAsnb.js +++ b/packages/ui/dist/copy/code-editor/runtime/chunks/display-l54fb8vw.js @@ -1,5 +1,5 @@ -import { i as all, l as make, o as enabled } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/display.js +import { i as all, l as make, o as enabled } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/display.js function avatar(root, { on }) { const frame = root.querySelector(".avatar"), fallback = root.querySelector("[data-avatar-fallback]"); if (!frame || !fallback) return {}; @@ -208,5 +208,4 @@ function developerView(root, { on }) { pre.textContent = String(text); } }; } -//#endregion export { editorSearch as i, chart as n, developerView as r, avatar as t }; diff --git a/packages/ui/dist/copy/code-editor/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/code-editor/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/code-editor/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/code-editor/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/code-editor/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/code-editor/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/code-editor/runtime/components/code-editor.js b/packages/ui/dist/copy/code-editor/runtime/components/code-editor.js index 9a989eb60..9ded595dc 100644 --- a/packages/ui/dist/copy/code-editor/runtime/components/code-editor.js +++ b/packages/ui/dist/copy/code-editor/runtime/components/code-editor.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as developerView } from "../chunks/display-Jm9bAsnb.js"; -//#region .cache/ui-build/entries/components/code-editor.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as developerView } from "../chunks/display-l54fb8vw.js"; +// .cache/ui-build/entries/components/code-editor.js var J3w1CodeEditor = class extends J3w1Element { static componentId = "code-editor"; static version = "4.0.0"; - static implementationId = "sha256-BBPVGsJGf2n0c4gfyDdfHQH3KYYqmiAAqqC2h3DlIcc="; + static implementationId = "sha256-e/CR+QHi8ifbX2a2jAioPk485xWfjfZ+T4m6GYDGtck="; static connect = developerView; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -13,5 +13,4 @@ var J3w1CodeEditor = class extends J3w1Element { return this._api.setText(...args); } }; -//#endregion export { J3w1CodeEditor }; diff --git a/packages/ui/dist/copy/code-editor/runtime/register/code-editor.js b/packages/ui/dist/copy/code-editor/runtime/register/code-editor.js index 91f3f8d5f..d1025828c 100644 --- a/packages/ui/dist/copy/code-editor/runtime/register/code-editor.js +++ b/packages/ui/dist/copy/code-editor/runtime/register/code-editor.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1CodeEditor } from "../components/code-editor.js"; -//#region .cache/ui-build/entries/register/code-editor.js +// .cache/ui-build/entries/register/code-editor.js var element = registerElement("j3w1-code-editor", J3w1CodeEditor); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/combobox/manifest.json b/packages/ui/dist/copy/combobox/manifest.json index 71f9df8e6..f12a67bd4 100644 --- a/packages/ui/dist/copy/combobox/manifest.json +++ b/packages/ui/dist/copy/combobox/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/combobox.md", "dependencies": [ "register/combobox.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/combobox.js", - "chunks/navigation-BfNzDYZB.js" + "chunks/navigation-CknoksQ5.js" ], "files": { - "runtime/register/combobox.js": "sha256-t7izNmL59Io74wyYT41Fq3jMXxWJ/5V4IeEkC0apDwY=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/combobox.js": "sha256-7kydwJcVW8U2c0ssJPwbR84tdqvYPN/lFqBuOGeDQpU=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", + "runtime/register/combobox.js": "sha256-m2UGZdlqKfsCnUJuIsT/I3mYjH6K0Y5R836lZqJSXWs=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/combobox.js": "sha256-M50QmcWZJm+1LBF0oMh7S3tuXjDoApW3kq5Lzf+s57I=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-8Hkgwo0uaQUx8y4ghR6eYfsYL07GWC6VT0p+F/wavGo=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/combobox/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/combobox/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/combobox/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/combobox/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/combobox/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/combobox/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/combobox/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/combobox/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/combobox/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/combobox/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/combobox/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/combobox/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/chunks/navigation-BfNzDYZB.js b/packages/ui/dist/copy/combobox/runtime/chunks/navigation-CknoksQ5.js similarity index 99% rename from packages/ui/dist/chunks/navigation-BfNzDYZB.js rename to packages/ui/dist/copy/combobox/runtime/chunks/navigation-CknoksQ5.js index db2779553..dfd1883e6 100644 --- a/packages/ui/dist/chunks/navigation-BfNzDYZB.js +++ b/packages/ui/dist/copy/combobox/runtime/chunks/navigation-CknoksQ5.js @@ -1,5 +1,5 @@ -import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/navigation.js +import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/navigation.js function tabs(root, { on }, listOverride) { const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); if (!list) return {}; @@ -373,5 +373,4 @@ function menu(root, { on }) { } }; } -//#endregion export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/combobox/runtime/components/combobox.js b/packages/ui/dist/copy/combobox/runtime/components/combobox.js index 098363263..a4a6bf59f 100644 --- a/packages/ui/dist/copy/combobox/runtime/components/combobox.js +++ b/packages/ui/dist/copy/combobox/runtime/components/combobox.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as combobox } from "../chunks/navigation-BfNzDYZB.js"; -//#region .cache/ui-build/entries/components/combobox.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as combobox } from "../chunks/navigation-CknoksQ5.js"; +// .cache/ui-build/entries/components/combobox.js var J3w1Combobox = class extends J3w1Element { static componentId = "combobox"; static version = "4.0.0"; - static implementationId = "sha256-vBw1BDsNiy6oYSbmjgh7x2T+43b2GYa+XmHte/upgpQ="; + static implementationId = "sha256-4vDZ0Hg+y5o1gXWLagkKP/imvwnGiDolN4DHBnOP+Xo="; static connect = combobox; static upgradeProperties = [ "disabled", @@ -44,5 +44,4 @@ var J3w1Combobox = class extends J3w1Element { }); } }; -//#endregion export { J3w1Combobox }; diff --git a/packages/ui/dist/copy/combobox/runtime/register/combobox.js b/packages/ui/dist/copy/combobox/runtime/register/combobox.js index 0441f87e8..e914b1233 100644 --- a/packages/ui/dist/copy/combobox/runtime/register/combobox.js +++ b/packages/ui/dist/copy/combobox/runtime/register/combobox.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Combobox } from "../components/combobox.js"; -//#region .cache/ui-build/entries/register/combobox.js +// .cache/ui-build/entries/register/combobox.js var element = registerElement("j3w1-combobox", J3w1Combobox); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/command-palette/manifest.json b/packages/ui/dist/copy/command-palette/manifest.json index 84ead41ba..08f27ea18 100644 --- a/packages/ui/dist/copy/command-palette/manifest.json +++ b/packages/ui/dist/copy/command-palette/manifest.json @@ -5,19 +5,19 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/command-palette.md", "dependencies": [ "register/command-palette.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/command-palette.js", - "chunks/advanced-CqBF0dSb.js", - "chunks/markup-DeQ4bEMR.js" + "chunks/advanced-BrFnVc0y.js", + "chunks/markup-AopKpwOF.js" ], "files": { - "runtime/register/command-palette.js": "sha256-SSDEUavPG+KZSHsxMuoACxT3IKIhzg9LNpUMj+pS9Gs=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/command-palette.js": "sha256-GlMjxlVVzdC74Yr4LjWbLwXWGrHkFnjBaJ4o9rJw9DE=", - "runtime/chunks/advanced-CqBF0dSb.js": "sha256-ozOzkRU6IeVGBqU3XQ0aLledkAi9vcs8dJdMQutVevs=", - "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", + "runtime/register/command-palette.js": "sha256-PedlHrZKS7ibQjvoHExGQ+zxHgj8xqJ0E2ymlCfKQfo=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/command-palette.js": "sha256-IQKcYTVvuVtfGr7iErnA5SPEPVN58stlc12ia6WDx44=", + "runtime/chunks/advanced-BrFnVc0y.js": "sha256-FVberBpKO49P/WGnxa61BTxhYsLnnvMFInur/TwjG44=", + "runtime/chunks/markup-AopKpwOF.js": "sha256-/Dn3cWEmlRQzeQAPVf+C0AooVb1pdIQeNeqd1fQVoPc=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-tiMnZi/dRu4gB3RP0zxXVpTrTvFZsCYaugfulxBVhTk=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/command-palette/runtime/chunks/advanced-CqBF0dSb.js b/packages/ui/dist/copy/command-palette/runtime/chunks/advanced-BrFnVc0y.js similarity index 98% rename from packages/ui/dist/copy/command-palette/runtime/chunks/advanced-CqBF0dSb.js rename to packages/ui/dist/copy/command-palette/runtime/chunks/advanced-BrFnVc0y.js index 4a5c45981..36e7638c4 100644 --- a/packages/ui/dist/copy/command-palette/runtime/chunks/advanced-CqBF0dSb.js +++ b/packages/ui/dist/copy/command-palette/runtime/chunks/advanced-BrFnVc0y.js @@ -1,6 +1,6 @@ -import { c as keyIndex, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-B7mo5Eq3.js"; -import { t as IDREFS } from "./markup-DeQ4bEMR.js"; -//#region packages/ui/src/behaviors/advanced.js +import { c as keyIndex, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-DqwWT5pJ.js"; +import { t as IDREFS } from "./markup-AopKpwOF.js"; +// packages/ui/src/behaviors/advanced.js function tree(root, { on }) { const treeRoot = root.querySelector("[role=\"tree\"]"); if (!treeRoot) return {}; @@ -341,5 +341,4 @@ function commandPalette(root, { on }) { cleanup: close }; } -//#endregion export { tree as i, multiselect as n, repeater as r, commandPalette as t }; diff --git a/packages/ui/dist/copy/command-palette/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/command-palette/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/command-palette/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/command-palette/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/command-palette/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/command-palette/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/command-palette/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/command-palette/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/command-palette/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/command-palette/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/command-palette/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/command-palette/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/chunks/markup-DeQ4bEMR.js b/packages/ui/dist/copy/command-palette/runtime/chunks/markup-AopKpwOF.js similarity index 97% rename from packages/ui/dist/chunks/markup-DeQ4bEMR.js rename to packages/ui/dist/copy/command-palette/runtime/chunks/markup-AopKpwOF.js index 77bd9471d..bc1c52c0b 100644 --- a/packages/ui/dist/chunks/markup-DeQ4bEMR.js +++ b/packages/ui/dist/copy/command-palette/runtime/chunks/markup-AopKpwOF.js @@ -1,4 +1,4 @@ -//#region scripts/lib/markup.mjs +// scripts/lib/markup.mjs var IDREFS = /* @__PURE__ */ new Set([ "for", "form", @@ -50,5 +50,4 @@ var namespaceMarkup = (tree, decorate, { strict = true, renameNames = false } = else if (renameNames && attr.name === "name") attr.value = decorate(attr.value); }); }; -//#endregion export { setAttribute as a, removeAttribute as i, hasClass as n, walkMarkup as o, namespaceMarkup as r, IDREFS as t }; diff --git a/packages/ui/dist/copy/command-palette/runtime/components/command-palette.js b/packages/ui/dist/copy/command-palette/runtime/components/command-palette.js index 196ad7f12..660108f21 100644 --- a/packages/ui/dist/copy/command-palette/runtime/components/command-palette.js +++ b/packages/ui/dist/copy/command-palette/runtime/components/command-palette.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as commandPalette } from "../chunks/advanced-CqBF0dSb.js"; -//#region .cache/ui-build/entries/components/command-palette.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as commandPalette } from "../chunks/advanced-BrFnVc0y.js"; +// .cache/ui-build/entries/components/command-palette.js var J3w1CommandPalette = class extends J3w1Element { static componentId = "command-palette"; static version = "4.0.0"; - static implementationId = "sha256-jnhxb+w/Xgrb5Os9Dxr1YHn/ex7fLJlGLSWZSpbrAuU="; + static implementationId = "sha256-6g0v2bCTEnlpiyCMMFs1KoDHyNPuVus2RWtD6Nlui6A="; static connect = commandPalette; static upgradeProperties = [ "disabled", @@ -36,5 +36,4 @@ var J3w1CommandPalette = class extends J3w1Element { }); } }; -//#endregion export { J3w1CommandPalette }; diff --git a/packages/ui/dist/copy/command-palette/runtime/register/command-palette.js b/packages/ui/dist/copy/command-palette/runtime/register/command-palette.js index 8c4d129ed..e13961e1c 100644 --- a/packages/ui/dist/copy/command-palette/runtime/register/command-palette.js +++ b/packages/ui/dist/copy/command-palette/runtime/register/command-palette.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1CommandPalette } from "../components/command-palette.js"; -//#region .cache/ui-build/entries/register/command-palette.js +// .cache/ui-build/entries/register/command-palette.js var element = registerElement("j3w1-command-palette", J3w1CommandPalette); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/compact-dashboard/manifest.json b/packages/ui/dist/copy/compact-dashboard/manifest.json index 3902db9ea..3a6375837 100644 --- a/packages/ui/dist/copy/compact-dashboard/manifest.json +++ b/packages/ui/dist/copy/compact-dashboard/manifest.json @@ -5,25 +5,25 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/compact-dashboard.md", "dependencies": [ "register/compact-dashboard.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "register/chart.js", "components/chart.js", - "chunks/display-Jm9bAsnb.js", + "chunks/display-l54fb8vw.js", "components/compact-dashboard.js", - "chunks/compositions-D57dCsBz.js", - "chunks/navigation-BfNzDYZB.js" + "chunks/compositions-DWG4tv9E.js", + "chunks/navigation-CknoksQ5.js" ], "files": { - "runtime/register/compact-dashboard.js": "sha256-hCoso+VES7vbCkeradjbcmoYaD/A7Zk2HcIGKzkkT1k=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/register/chart.js": "sha256-T98hQYpUxEQ3kRDeztnuOxP5XmwfddBBocBZ3rdTxT8=", - "runtime/components/chart.js": "sha256-hVyc1MgrIwRQZWPz61YJX6ScFRhDJTjMKtYEs5Xtxoo=", - "runtime/chunks/display-Jm9bAsnb.js": "sha256-qZb1g04piEwY3lfFJwMe+0mXR218ljtVi8mepWxrFv8=", - "runtime/components/compact-dashboard.js": "sha256-Y2R2ASCxDuMVCbBdUqOGP60JpwtPCK17jCjpQXz1hhE=", - "runtime/chunks/compositions-D57dCsBz.js": "sha256-PEpI/vGgdD+LSznUd0iedSxxVE+5QxIO7BGKeQnCRjo=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", + "runtime/register/compact-dashboard.js": "sha256-P8HNsRbiUifDMRZHPW2MbhfKm+dn03BeYVKCHO8pd5A=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/register/chart.js": "sha256-andwTROOZAuydVX/8AHv1ch78Vp2Bpfw0e1QhJuc1H8=", + "runtime/components/chart.js": "sha256-b+gmdldG475mc83KqS69DHLQ3yWt0OTgOk+UNqB5J9o=", + "runtime/chunks/display-l54fb8vw.js": "sha256-xfzo614uMLlSbZc5l+o4vHvrL8yBjQAcV/HJdmPUJ/g=", + "runtime/components/compact-dashboard.js": "sha256-YBUDjeM+Qi1QpjrdGLeWThioY1qC2/SilmX5Le+aUpA=", + "runtime/chunks/compositions-DWG4tv9E.js": "sha256-vV/UcQrj3UFpVXymFuH4t/h/T+7JqBeND9xuyVdCjqo=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-7CRIHJNTDt06T3ztva5EpY4ytKr+vSsMZHxxolQ/+GU=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/file-browser/runtime/chunks/compositions-D57dCsBz.js b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/compositions-DWG4tv9E.js similarity index 91% rename from packages/ui/dist/copy/file-browser/runtime/chunks/compositions-D57dCsBz.js rename to packages/ui/dist/copy/compact-dashboard/runtime/chunks/compositions-DWG4tv9E.js index f1da4562e..aa98d384a 100644 --- a/packages/ui/dist/copy/file-browser/runtime/chunks/compositions-D57dCsBz.js +++ b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/compositions-DWG4tv9E.js @@ -1,6 +1,6 @@ -import { i as all, o as enabled } from "./choice-B7mo5Eq3.js"; -import { i as tabs } from "./navigation-BfNzDYZB.js"; -//#region packages/ui/src/behaviors/compositions.js +import { i as all, o as enabled } from "./choice-DqwWT5pJ.js"; +import { i as tabs } from "./navigation-CknoksQ5.js"; +// packages/ui/src/behaviors/compositions.js function fileBrowser(root, { on }) { const query = root.querySelector("[data-file-query]"), rows = all(root, "tr[data-file-id]"), status = root.querySelector("[data-file-status]"); let location = "all"; @@ -47,5 +47,4 @@ function windowFrame(root, context) { }); return {}; } -//#endregion export { fileBrowser as n, windowFrame as r, dashboard as t }; diff --git a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/display-Jm9bAsnb.js b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/display-Jm9bAsnb.js deleted file mode 100644 index 5bc817830..000000000 --- a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/display-Jm9bAsnb.js +++ /dev/null @@ -1,212 +0,0 @@ -import { i as all, l as make, o as enabled } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/display.js -function avatar(root, { on }) { - const frame = root.querySelector(".avatar"), fallback = root.querySelector("[data-avatar-fallback]"); - if (!frame || !fallback) return {}; - let image = frame.querySelector("img"); - if (!image) { - image = make(root, "img", { - alt: "", - hidden: "" - }); - frame.prepend(image); - } - let source = image.getAttribute("src") ?? ""; - const update = (value) => { - source = String(value ?? ""); - image.hidden = true; - fallback.hidden = false; - delete frame.dataset.error; - if (!source) { - image.removeAttribute("src"); - delete frame.dataset.loading; - return; - } - frame.dataset.loading = "true"; - image.src = source; - }; - on(image, "load", () => { - delete frame.dataset.loading; - image.hidden = false; - fallback.hidden = true; - }); - on(image, "error", () => { - delete frame.dataset.loading; - frame.dataset.error = "true"; - image.hidden = true; - fallback.hidden = false; - }); - update(root.getAttribute("src") ?? source); - return { - get src() { - return source; - }, - set src(value) { - update(value); - }, - attributeChanged(name) { - if (name === "src") update(root.getAttribute("src")); - } - }; -} -function chart(root) { - const figure = root.querySelector("figure"), svg = figure?.querySelector("svg"), tbody = figure?.querySelector("tbody"); - if (!figure || !svg || !tbody) return {}; - let values = all(tbody, "tr").map((row) => ({ - label: row.cells[0]?.textContent.trim() ?? "", - value: Number(row.cells[1]?.textContent) - })); - const update = (data) => { - if (!Array.isArray(data) || data.length > 200 || data.some((row) => typeof row.label !== "string" || typeof row.value !== "number" || !Number.isFinite(row.value) || row.value < 0)) throw new TypeError("data must contain at most 200 labelled finite non-negative values"); - values = data.map((row) => ({ - label: row.label, - value: row.value - })); - svg.replaceChildren(); - tbody.replaceChildren(); - const ns = "http://www.w3.org/2000/svg"; - const group = root.ownerDocument.createElementNS(ns, "g"); - group.setAttribute("class", "chart-series"); - svg.append(group); - const width = Math.max(300, values.length * 32), max = Math.max(1, ...values.map((row) => row.value)); - svg.setAttribute("viewBox", `0 0 ${width} 140`); - svg.setAttribute("aria-label", values.length ? values.map((row) => `${row.label}: ${row.value}`).join("; ") : "No data available"); - for (const [index, row] of values.entries()) { - const bar = root.ownerDocument.createElementNS(ns, "rect"), step = (width - 20) / values.length, height = row.value / max * 100; - for (const [name, value] of Object.entries({ - x: 10 + index * step + step * .15, - y: 110 - height, - width: step * .7, - height - })) bar.setAttribute(name, String(value)); - const title = root.ownerDocument.createElementNS(ns, "title"); - title.textContent = `${row.label}: ${row.value}`; - bar.append(title); - group.append(bar); - const tr = make(root, "tr"); - tr.append(make(root, "th", { scope: "row" }, row.label), make(root, "td", {}, row.value)); - tbody.append(tr); - } - svg.toggleAttribute("hidden", !values.length); - const empty = figure.querySelector("[data-chart-empty]"); - if (empty) empty.hidden = values.length !== 0; - }; - return { - get data() { - return values.map((row) => ({ ...row })); - }, - set data(data) { - update(data); - } - }; -} -function editorSearch(root, { on }) { - const input = root.querySelector("[data-query]"), pre = root.querySelector("[data-source]"), status = root.querySelector("[data-search-status]"); - if (!input || !pre) return {}; - let source = pre.textContent, current = -1, matches = []; - const previous = root.querySelector("[data-previous]"), following = root.querySelector("[data-next]"); - const select = (index) => { - current = matches.length ? (index + matches.length) % matches.length : -1; - all(pre, "mark").forEach((mark, i) => mark.toggleAttribute("data-current", i === current)); - if (status) status.textContent = !input.value ? "Enter text to search." : matches.length ? `Match ${current + 1} of ${matches.length}` : "No matches."; - }; - const search = () => { - matches = []; - pre.replaceChildren(); - const query = input.value.toLocaleLowerCase(); - let folded = "", offset = 0; - const starts = [], ends = []; - for (const char of source) { - const text = char.toLocaleLowerCase(); - for (let i = 0; i < text.length; i++) { - starts.push(offset); - ends.push(offset + char.length); - } - folded += text; - offset += char.length; - } - if (query) { - let position = 0; - while ((position = folded.indexOf(query, position)) >= 0) { - const start = starts[position], end = ends[position + query.length - 1]; - if (!matches.length || start >= matches.at(-1).end) matches.push({ - start, - end - }); - position += query.length; - } - } - let cursor = 0; - for (const match of matches) { - pre.append(root.ownerDocument.createTextNode(source.slice(cursor, match.start)), make(root, "mark", {}, source.slice(match.start, match.end))); - cursor = match.end; - } - pre.append(root.ownerDocument.createTextNode(source.slice(cursor))); - if (previous) previous.disabled = !matches.length; - if (following) following.disabled = !matches.length; - select(0); - }; - const next = (direction = 1) => { - if (!matches.length) return; - select(current + (direction < 0 ? -1 : 1)); - all(pre, "mark")[current]?.scrollIntoView({ - block: "nearest", - inline: "nearest" - }); - }; - on(input, "input", search); - on(input, "keydown", (event) => { - if (event.key === "Enter") { - event.preventDefault(); - next(event.shiftKey ? -1 : 1); - } else if (event.key === "Escape" && input.value) { - event.preventDefault(); - event.stopPropagation(); - input.value = ""; - search(); - } - }); - on(previous, "click", () => next(-1)); - on(following, "click", () => next()); - search(); - return { - next, - get source() { - return source; - }, - set source(text) { - source = String(text); - search(); - }, - get query() { - return input.value; - }, - set query(value) { - input.value = String(value); - search(); - }, - get matchCount() { - return matches.length; - } - }; -} -function developerView(root, { on }) { - on(root, "click", (event) => { - const action = event.target.closest("button,[data-action]"); - if (action && enabled(action)) root.emit("action", { action: action.dataset.action ?? action.textContent.trim() }); - }); - return { setText(text) { - let pre = root.querySelector("pre"); - if (!pre) { - pre = make(root, "pre", { - class: "j3w1-readonly-text", - tabindex: "0", - "aria-label": "Read-only text" - }); - root.firstElementChild.replaceChildren(pre); - } - pre.textContent = String(text); - } }; -} -//#endregion -export { editorSearch as i, chart as n, developerView as r, avatar as t }; diff --git a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/display-l54fb8vw.js b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/display-l54fb8vw.js new file mode 100644 index 000000000..b2f57aaf2 --- /dev/null +++ b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/display-l54fb8vw.js @@ -0,0 +1,211 @@ +import { i as all, l as make, o as enabled } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/display.js +function avatar(root, { on }) { + const frame = root.querySelector(".avatar"), fallback = root.querySelector("[data-avatar-fallback]"); + if (!frame || !fallback) return {}; + let image = frame.querySelector("img"); + if (!image) { + image = make(root, "img", { + alt: "", + hidden: "" + }); + frame.prepend(image); + } + let source = image.getAttribute("src") ?? ""; + const update = (value) => { + source = String(value ?? ""); + image.hidden = true; + fallback.hidden = false; + delete frame.dataset.error; + if (!source) { + image.removeAttribute("src"); + delete frame.dataset.loading; + return; + } + frame.dataset.loading = "true"; + image.src = source; + }; + on(image, "load", () => { + delete frame.dataset.loading; + image.hidden = false; + fallback.hidden = true; + }); + on(image, "error", () => { + delete frame.dataset.loading; + frame.dataset.error = "true"; + image.hidden = true; + fallback.hidden = false; + }); + update(root.getAttribute("src") ?? source); + return { + get src() { + return source; + }, + set src(value) { + update(value); + }, + attributeChanged(name) { + if (name === "src") update(root.getAttribute("src")); + } + }; +} +function chart(root) { + const figure = root.querySelector("figure"), svg = figure?.querySelector("svg"), tbody = figure?.querySelector("tbody"); + if (!figure || !svg || !tbody) return {}; + let values = all(tbody, "tr").map((row) => ({ + label: row.cells[0]?.textContent.trim() ?? "", + value: Number(row.cells[1]?.textContent) + })); + const update = (data) => { + if (!Array.isArray(data) || data.length > 200 || data.some((row) => typeof row.label !== "string" || typeof row.value !== "number" || !Number.isFinite(row.value) || row.value < 0)) throw new TypeError("data must contain at most 200 labelled finite non-negative values"); + values = data.map((row) => ({ + label: row.label, + value: row.value + })); + svg.replaceChildren(); + tbody.replaceChildren(); + const ns = "http://www.w3.org/2000/svg"; + const group = root.ownerDocument.createElementNS(ns, "g"); + group.setAttribute("class", "chart-series"); + svg.append(group); + const width = Math.max(300, values.length * 32), max = Math.max(1, ...values.map((row) => row.value)); + svg.setAttribute("viewBox", `0 0 ${width} 140`); + svg.setAttribute("aria-label", values.length ? values.map((row) => `${row.label}: ${row.value}`).join("; ") : "No data available"); + for (const [index, row] of values.entries()) { + const bar = root.ownerDocument.createElementNS(ns, "rect"), step = (width - 20) / values.length, height = row.value / max * 100; + for (const [name, value] of Object.entries({ + x: 10 + index * step + step * .15, + y: 110 - height, + width: step * .7, + height + })) bar.setAttribute(name, String(value)); + const title = root.ownerDocument.createElementNS(ns, "title"); + title.textContent = `${row.label}: ${row.value}`; + bar.append(title); + group.append(bar); + const tr = make(root, "tr"); + tr.append(make(root, "th", { scope: "row" }, row.label), make(root, "td", {}, row.value)); + tbody.append(tr); + } + svg.toggleAttribute("hidden", !values.length); + const empty = figure.querySelector("[data-chart-empty]"); + if (empty) empty.hidden = values.length !== 0; + }; + return { + get data() { + return values.map((row) => ({ ...row })); + }, + set data(data) { + update(data); + } + }; +} +function editorSearch(root, { on }) { + const input = root.querySelector("[data-query]"), pre = root.querySelector("[data-source]"), status = root.querySelector("[data-search-status]"); + if (!input || !pre) return {}; + let source = pre.textContent, current = -1, matches = []; + const previous = root.querySelector("[data-previous]"), following = root.querySelector("[data-next]"); + const select = (index) => { + current = matches.length ? (index + matches.length) % matches.length : -1; + all(pre, "mark").forEach((mark, i) => mark.toggleAttribute("data-current", i === current)); + if (status) status.textContent = !input.value ? "Enter text to search." : matches.length ? `Match ${current + 1} of ${matches.length}` : "No matches."; + }; + const search = () => { + matches = []; + pre.replaceChildren(); + const query = input.value.toLocaleLowerCase(); + let folded = "", offset = 0; + const starts = [], ends = []; + for (const char of source) { + const text = char.toLocaleLowerCase(); + for (let i = 0; i < text.length; i++) { + starts.push(offset); + ends.push(offset + char.length); + } + folded += text; + offset += char.length; + } + if (query) { + let position = 0; + while ((position = folded.indexOf(query, position)) >= 0) { + const start = starts[position], end = ends[position + query.length - 1]; + if (!matches.length || start >= matches.at(-1).end) matches.push({ + start, + end + }); + position += query.length; + } + } + let cursor = 0; + for (const match of matches) { + pre.append(root.ownerDocument.createTextNode(source.slice(cursor, match.start)), make(root, "mark", {}, source.slice(match.start, match.end))); + cursor = match.end; + } + pre.append(root.ownerDocument.createTextNode(source.slice(cursor))); + if (previous) previous.disabled = !matches.length; + if (following) following.disabled = !matches.length; + select(0); + }; + const next = (direction = 1) => { + if (!matches.length) return; + select(current + (direction < 0 ? -1 : 1)); + all(pre, "mark")[current]?.scrollIntoView({ + block: "nearest", + inline: "nearest" + }); + }; + on(input, "input", search); + on(input, "keydown", (event) => { + if (event.key === "Enter") { + event.preventDefault(); + next(event.shiftKey ? -1 : 1); + } else if (event.key === "Escape" && input.value) { + event.preventDefault(); + event.stopPropagation(); + input.value = ""; + search(); + } + }); + on(previous, "click", () => next(-1)); + on(following, "click", () => next()); + search(); + return { + next, + get source() { + return source; + }, + set source(text) { + source = String(text); + search(); + }, + get query() { + return input.value; + }, + set query(value) { + input.value = String(value); + search(); + }, + get matchCount() { + return matches.length; + } + }; +} +function developerView(root, { on }) { + on(root, "click", (event) => { + const action = event.target.closest("button,[data-action]"); + if (action && enabled(action)) root.emit("action", { action: action.dataset.action ?? action.textContent.trim() }); + }); + return { setText(text) { + let pre = root.querySelector("pre"); + if (!pre) { + pre = make(root, "pre", { + class: "j3w1-readonly-text", + tabindex: "0", + "aria-label": "Read-only text" + }); + root.firstElementChild.replaceChildren(pre); + } + pre.textContent = String(text); + } }; +} +export { editorSearch as i, chart as n, developerView as r, avatar as t }; diff --git a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/compact-dashboard/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/combobox/runtime/chunks/navigation-BfNzDYZB.js b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/navigation-CknoksQ5.js similarity index 99% rename from packages/ui/dist/copy/combobox/runtime/chunks/navigation-BfNzDYZB.js rename to packages/ui/dist/copy/compact-dashboard/runtime/chunks/navigation-CknoksQ5.js index db2779553..dfd1883e6 100644 --- a/packages/ui/dist/copy/combobox/runtime/chunks/navigation-BfNzDYZB.js +++ b/packages/ui/dist/copy/compact-dashboard/runtime/chunks/navigation-CknoksQ5.js @@ -1,5 +1,5 @@ -import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/navigation.js +import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/navigation.js function tabs(root, { on }, listOverride) { const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); if (!list) return {}; @@ -373,5 +373,4 @@ function menu(root, { on }) { } }; } -//#endregion export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/compact-dashboard/runtime/components/chart.js b/packages/ui/dist/copy/compact-dashboard/runtime/components/chart.js index 70d90b671..1be85f8ea 100644 --- a/packages/ui/dist/copy/compact-dashboard/runtime/components/chart.js +++ b/packages/ui/dist/copy/compact-dashboard/runtime/components/chart.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as chart } from "../chunks/display-Jm9bAsnb.js"; -//#region .cache/ui-build/entries/components/chart.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as chart } from "../chunks/display-l54fb8vw.js"; +// .cache/ui-build/entries/components/chart.js var J3w1Chart = class extends J3w1Element { static componentId = "chart"; static version = "4.0.0"; - static implementationId = "sha256-48dT14XNNF9ZyV4PB4oLs8zT/lNQqNt9rXZCl9gUYVc="; + static implementationId = "sha256-PhBwyLjFdcq2bXYtZewk49w7vPNGTKA3c6iz1WayLys="; static connect = chart; static upgradeProperties = [ "disabled", @@ -24,5 +24,4 @@ var J3w1Chart = class extends J3w1Element { }); } }; -//#endregion export { J3w1Chart }; diff --git a/packages/ui/dist/copy/compact-dashboard/runtime/components/compact-dashboard.js b/packages/ui/dist/copy/compact-dashboard/runtime/components/compact-dashboard.js index b29237379..44a81ddba 100644 --- a/packages/ui/dist/copy/compact-dashboard/runtime/components/compact-dashboard.js +++ b/packages/ui/dist/copy/compact-dashboard/runtime/components/compact-dashboard.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as dashboard } from "../chunks/compositions-D57dCsBz.js"; -//#region .cache/ui-build/entries/components/compact-dashboard.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as dashboard } from "../chunks/compositions-DWG4tv9E.js"; +// .cache/ui-build/entries/components/compact-dashboard.js var J3w1CompactDashboard = class extends J3w1Element { static componentId = "compact-dashboard"; static version = "4.0.0"; - static implementationId = "sha256-Shp675PVGMGOiXxiKpeWEQHQugGKEIbNO/jz8KwP4m0="; + static implementationId = "sha256-XGMk6csk8qspD/G8I2T9TzGnFhunqMgxXUJbb9/81pY="; static connect = dashboard; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1CompactDashboard }; diff --git a/packages/ui/dist/copy/compact-dashboard/runtime/register/chart.js b/packages/ui/dist/copy/compact-dashboard/runtime/register/chart.js index 8efbe0a3f..e1c79eef1 100644 --- a/packages/ui/dist/copy/compact-dashboard/runtime/register/chart.js +++ b/packages/ui/dist/copy/compact-dashboard/runtime/register/chart.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Chart } from "../components/chart.js"; -//#region .cache/ui-build/entries/register/chart.js +// .cache/ui-build/entries/register/chart.js var element = registerElement("j3w1-chart", J3w1Chart); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/compact-dashboard/runtime/register/compact-dashboard.js b/packages/ui/dist/copy/compact-dashboard/runtime/register/compact-dashboard.js index 6a2980828..01847187f 100644 --- a/packages/ui/dist/copy/compact-dashboard/runtime/register/compact-dashboard.js +++ b/packages/ui/dist/copy/compact-dashboard/runtime/register/compact-dashboard.js @@ -1,7 +1,6 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import "./chart.js"; import { J3w1CompactDashboard } from "../components/compact-dashboard.js"; -//#region .cache/ui-build/entries/register/compact-dashboard.js +// .cache/ui-build/entries/register/compact-dashboard.js var element = registerElement("j3w1-compact-dashboard", J3w1CompactDashboard); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/data-table/manifest.json b/packages/ui/dist/copy/data-table/manifest.json index 21bc90cda..ce04ed6ff 100644 --- a/packages/ui/dist/copy/data-table/manifest.json +++ b/packages/ui/dist/copy/data-table/manifest.json @@ -5,23 +5,23 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/data-table.md", "dependencies": [ "register/data-table.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "register/menu.js", "components/menu.js", - "chunks/navigation-BfNzDYZB.js", + "chunks/navigation-CknoksQ5.js", "components/data-table.js", - "chunks/tables-Cjr1EIJz.js" + "chunks/tables-zo8ebTOo.js" ], "files": { - "runtime/register/data-table.js": "sha256-wrLpuRzCJQhN8Kx+gdh/HOPhsNQP/wrnopu8NmJsUm0=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/register/menu.js": "sha256-6CvU7Rei9lC+olXvluxdbCPqh46GrPSvB2MGiudiMTk=", - "runtime/components/menu.js": "sha256-As/aVex/jKXrmY4x/rG0tVMVUij8ZLPXK0kKS4ZBpSQ=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", - "runtime/components/data-table.js": "sha256-Du0JOAv8n9YEK04c217gbbmS25D1Yfx4irEe/DIPLk4=", - "runtime/chunks/tables-Cjr1EIJz.js": "sha256-K6BF6M6xNawgWdL+NIcBRZmY98j45o69tBI034Ks4Bg=", + "runtime/register/data-table.js": "sha256-Q9RijAjLomTWYsCq2oBB0nqzctnSczqxn2SN/kO9hEo=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/register/menu.js": "sha256-du/4u8ykElicgf7iZHv6rD5yz/4njOxzodjcqCcr0d8=", + "runtime/components/menu.js": "sha256-qz11rQvGk4omYnKEFWVz4SXD3R4xn/UhG0nt4oqFtJw=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", + "runtime/components/data-table.js": "sha256-RCZWFa2cvBMJVcELbxOnA7yDNokUGtGXj1ok+Xl+l2o=", + "runtime/chunks/tables-zo8ebTOo.js": "sha256-+LRPZmFKPk0oe8q3HDlfXCXkloBbkRbiFHVHczc3GEs=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-T5PnYnMx2i60rNgYfN/tfLrncLf9cAlC4gsLpnSw/b4=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/data-table/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/data-table/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/data-table/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/data-table/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/data-table/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/data-table/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/data-table/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/data-table/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/data-table/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/data-table/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/data-table/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/data-table/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/data-table/runtime/chunks/navigation-BfNzDYZB.js b/packages/ui/dist/copy/data-table/runtime/chunks/navigation-BfNzDYZB.js deleted file mode 100644 index db2779553..000000000 --- a/packages/ui/dist/copy/data-table/runtime/chunks/navigation-BfNzDYZB.js +++ /dev/null @@ -1,377 +0,0 @@ -import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/navigation.js -function tabs(root, { on }, listOverride) { - const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); - if (!list) return {}; - const items = () => all(list, "[role=\"tab\"]").filter(enabled); - const select = (id, focus = false) => { - const tab = items().find((item) => item.id === id); - if (!tab) throw new RangeError(`Unknown enabled tab: ${id}`); - all(list, "[role=\"tab\"]").forEach((item) => { - item.setAttribute("aria-selected", String(item === tab)); - item.tabIndex = item === tab ? 0 : -1; - }); - all(root, "[role=\"tabpanel\"]").filter((panel) => all(list, "[role=\"tab\"]").some((tab) => tab.getAttribute("aria-controls") === panel.id)).forEach((panel) => { - panel.hidden = panel.id !== tab.getAttribute("aria-controls"); - if (!panel.hidden && !panel.querySelector("a[href],button,input,select,textarea,[tabindex='0']")) panel.tabIndex = 0; - }); - if (focus) tab.focus(); - return tab; - }; - const activate = (tab) => { - select(tab.id); - root.emit("select", { - id: tab.id, - panelId: tab.getAttribute("aria-controls") - }); - }; - on(list, "click", (event) => { - const tab = event.target.closest("[role=\"tab\"]"); - if (tab && enabled(tab)) activate(tab); - }); - on(list, "keydown", (event) => { - const current = event.target.closest("[role=\"tab\"]"), options = items(); - if (!current) return; - const vertical = list.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(list).direction === "rtl"; - const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", previous = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; - let index = options.indexOf(current); - if (event.key === next) index++; - else if (event.key === previous) index--; - else if (event.key === "Home") index = 0; - else if (event.key === "End") index = options.length - 1; - else if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - activate(current); - return; - } else return; - event.preventDefault(); - const tab = rove(options, index); - if (root.getAttribute("activation") !== "manual") activate(tab); - }); - const initial = items().find((item) => item.getAttribute("aria-selected") === "true") ?? items()[0]; - if (initial) select(initial.id); - return { - select, - get selectedId() { - return list.querySelector("[aria-selected=\"true\"]")?.id ?? ""; - }, - set selectedId(id) { - select(id); - } - }; -} -function toolbar(root, { on }) { - const bar = root.querySelector("[role=\"toolbar\"]"); - if (!bar) return {}; - const controls = () => all(bar, "button,a[href],input,select").filter((node) => enabled(node) && visible(node) && !node.closest("[role=\"menu\"]")); - const initial = controls(); - rove(initial, Math.max(0, initial.findIndex((node) => node.tabIndex === 0)), false); - on(bar, "focusin", (event) => { - if (controls().includes(event.target)) rove(controls(), controls().indexOf(event.target), false); - }); - on(bar, "keydown", (event) => { - if (event.target.matches("input,select,textarea") || event.target.closest("[role=\"menu\"]")) return; - const items = controls(), index = items.indexOf(event.target); - const vertical = bar.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(bar).direction === "rtl"; - const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", prev = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; - if (![ - next, - prev, - "Home", - "End" - ].includes(event.key)) return; - event.preventDefault(); - rove(items, keyIndex({ - key: event.key, - index, - length: items.length, - next, - previous: prev - })); - }); - on(bar, "click", (event) => { - const button = event.target.closest("button[aria-pressed]"); - if (button && enabled(button)) { - button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - root.emit("action", { - action: button.dataset.action ?? button.textContent.trim(), - pressed: button.getAttribute("aria-pressed") === "true" - }); - } - }); - return {}; -} -function disclosure(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button[aria-controls][aria-expanded]"); - if (!button || !enabled(button)) return; - const target = root.querySelector(`#${CSS.escape(button.getAttribute("aria-controls"))}`); - if (!target) return; - const expanded = button.getAttribute("aria-expanded") !== "true"; - button.setAttribute("aria-expanded", String(expanded)); - target.hidden = !expanded; - root.emit("toggle", { - id: target.id, - expanded - }); - }); - const details = root.querySelector("details"); - on(details, "toggle", () => root.emit("toggle", { - id: details.id, - expanded: details.open - })); - return { - get open() { - return details?.open ?? false; - }, - set open(value) { - if (details) details.open = Boolean(value); - } - }; -} -function combobox(root, { on, signal }) { - const input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"); - if (!input || !list) return {}; - identify(root, list, "options"); - input.setAttribute("aria-controls", list.id); - let active = null, notifying = false; - const notify = () => { - notifying = true; - try { - nativeInput(input); - nativeInput(input, "change"); - } finally { - notifying = false; - } - }; - const options = () => all(list, "[role=\"option\"]").filter((node) => enabled(node) && !node.hidden && !node.closest("[role=\"group\"][hidden]")); - all(list, "[role=\"option\"]").forEach((option, index) => identify(root, option, `option-${index}`)); - const setActive = (option) => { - active = option; - all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); - if (option) { - input.setAttribute("aria-activedescendant", option.id); - option.scrollIntoView({ block: "nearest" }); - } else input.removeAttribute("aria-activedescendant"); - }; - const hide = () => { - list.hidden = true; - input.setAttribute("aria-expanded", "false"); - setActive(null); - }; - const filter = (query = input.value) => { - for (const option of all(list, "[role=\"option\"]")) if (enabled(option)) option.hidden = !option.textContent.toLocaleLowerCase().includes(query.toLocaleLowerCase()); - all(list, "[role=\"group\"]").forEach((group) => { - group.hidden = !all(group, "[role=\"option\"]").some((node) => enabled(node) && !node.hidden); - }); - const empty = root.querySelector(".combobox-empty"); - if (empty) { - empty.hidden = options().length !== 0; - empty.classList.toggle("combobox-empty-shown", !empty.hidden); - } - if (!options().includes(active)) setActive(null); - }; - const show = (allOptions = false) => { - if (!enabled(input) || input.readOnly) return; - filter(allOptions ? "" : input.value); - list.hidden = false; - input.setAttribute("aria-expanded", "true"); - place(input, list); - }; - const choose = (option) => { - if (!option || !enabled(option)) return; - input.value = option.dataset.value ?? option.textContent.trim(); - hide(); - notify(); - input.focus(); - }; - on(input, "input", () => { - if (!notifying) { - show(); - announce(root, `${options().length} options available.`); - } - }); - on(input, "keydown", (event) => { - if (event.key === "Tab") { - hide(); - return; - } - if (event.key === "Escape") { - if (!list.hidden) { - hide(); - event.stopPropagation(); - } else if (input.value) { - input.value = ""; - notify(); - event.stopPropagation(); - } - event.preventDefault(); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - hide(); - return; - } - if (["ArrowDown", "ArrowUp"].includes(event.key)) { - event.preventDefault(); - if (list.hidden) show(true); - if (event.altKey) return; - const items = options(), index = active ? items.indexOf(active) : event.key === "ArrowDown" ? -1 : 0; - if (items.length) setActive(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); - } else if (event.key === "Enter" && !list.hidden && active) { - event.preventDefault(); - choose(active); - } - }); - on(list, "pointerdown", (event) => { - if (event.target.closest("[role=\"option\"]")) event.preventDefault(); - }); - on(list, "click", (event) => choose(event.target.closest("[role=\"option\"]"))); - on(root.querySelector(".combobox-toggle"), "click", () => { - list.hidden ? show(true) : hide(); - input.focus(); - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!root.contains(event.target)) hide(); - }); - on(root, "focusout", () => queueMicrotask(() => { - if (!signal.aborted && !root.contains(root.ownerDocument.activeElement)) hide(); - })); - on(root.ownerDocument.defaultView, "resize", () => { - if (!list.hidden) place(input, list); - }); - on(root.ownerDocument, "scroll", (event) => { - if (!list.hidden && !list.contains(event.target)) place(input, list); - }, { capture: true }); - hide(); - return { - show, - hide, - get open() { - return !list.hidden; - }, - set open(value) { - value ? show() : hide(); - }, - get value() { - return input.value; - }, - set value(value) { - input.value = String(value ?? ""); - if (!list.hidden) filter(); - }, - cleanup: hide - }; -} -function menu(root, { on }) { - const trigger = root.querySelector("button[aria-haspopup=\"menu\"]"), main = root.querySelector("[role=\"menu\"]"); - if (!trigger || !main) return {}; - identify(root, main, "menu"); - trigger.setAttribute("aria-controls", main.id); - const lists = all(root, "[role=\"menu\"]"); - const items = (list) => all(list, "[role^=\"menuitem\"]").filter((item) => item.closest("[role=\"menu\"]") === list); - const controller = (list) => all(root, "[aria-controls]").find((node) => node.getAttribute("aria-controls") === list.id); - const closeList = (list) => { - list.hidden = true; - controller(list)?.setAttribute("aria-expanded", "false"); - }; - const hide = (focus = true) => { - lists.forEach(closeList); - if (focus) trigger.focus(); - }; - const showList = (list, button, last = false) => { - list.hidden = false; - button.setAttribute("aria-expanded", "true"); - place(button, list); - rove(items(list), last ? items(list).length - 1 : 0); - }; - const show = () => { - if (enabled(trigger)) showList(main, trigger); - }; - const submenu = (button) => button.hasAttribute("aria-haspopup") ? lists.find((list) => list.id === button.getAttribute("aria-controls")) : null; - const activate = (item) => { - if (!enabled(item)) return; - const child = submenu(item); - if (child) { - showList(child, item); - return; - } - if (item.getAttribute("role") === "menuitemcheckbox") item.setAttribute("aria-checked", String(item.getAttribute("aria-checked") !== "true")); - else if (item.getAttribute("role") === "menuitemradio") items(item.closest("[role=\"menu\"]")).filter((node) => node.getAttribute("role") === "menuitemradio").forEach((node) => node.setAttribute("aria-checked", String(node === item))); - else hide(); - root.emit("action", { - action: item.dataset.action ?? item.textContent.trim(), - checked: item.getAttribute("aria-checked") === "true" - }); - }; - on(trigger, "click", () => main.hidden ? show() : hide()); - on(trigger, "keydown", (event) => { - if (["ArrowDown", "ArrowUp"].includes(event.key) && enabled(trigger)) { - event.preventDefault(); - showList(main, trigger, event.key === "ArrowUp"); - } - }); - on(root, "click", (event) => { - const item = event.target.closest("[role^=\"menuitem\"]"); - if (item) activate(item); - }); - on(root, "keydown", (event) => { - const item = event.target.closest("[role^=\"menuitem\"]"); - if (!item) return; - const list = item.closest("[role=\"menu\"]"), options = items(list), index = options.indexOf(item), rtl = getComputedStyle(list).direction === "rtl"; - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - rove(options, keyIndex({ - key: event.key, - index, - length: options.length - })); - } else if (event.key === "Escape" || event.key === (rtl ? "ArrowRight" : "ArrowLeft") && list !== main) { - event.preventDefault(); - event.stopPropagation(); - if (list !== main) { - closeList(list); - controller(list)?.focus(); - } else hide(); - } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight") && submenu(item)) { - event.preventDefault(); - showList(submenu(item), item); - } else if (event.key === "Tab") hide(); - else if (event.key.length === 1 && /\S/.test(event.key)) { - const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(".menu-label") ?? node).textContent.trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); - if (found) { - event.preventDefault(); - rove(options, options.indexOf(found)); - } - } - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!root.contains(event.target)) hide(false); - }); - on(root.ownerDocument, "focusin", (event) => { - if (!root.contains(event.target)) hide(false); - }); - on(root.ownerDocument.defaultView, "resize", () => lists.filter((list) => !list.hidden).forEach((list) => place(controller(list), list))); - hide(false); - return { - show, - hide, - get open() { - return !main.hidden; - }, - set open(value) { - value ? show() : hide(false); - }, - cleanup() { - hide(false); - } - }; -} -//#endregion -export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/data-table/runtime/chunks/navigation-CknoksQ5.js b/packages/ui/dist/copy/data-table/runtime/chunks/navigation-CknoksQ5.js new file mode 100644 index 000000000..dfd1883e6 --- /dev/null +++ b/packages/ui/dist/copy/data-table/runtime/chunks/navigation-CknoksQ5.js @@ -0,0 +1,376 @@ +import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/navigation.js +function tabs(root, { on }, listOverride) { + const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); + if (!list) return {}; + const items = () => all(list, "[role=\"tab\"]").filter(enabled); + const select = (id, focus = false) => { + const tab = items().find((item) => item.id === id); + if (!tab) throw new RangeError(`Unknown enabled tab: ${id}`); + all(list, "[role=\"tab\"]").forEach((item) => { + item.setAttribute("aria-selected", String(item === tab)); + item.tabIndex = item === tab ? 0 : -1; + }); + all(root, "[role=\"tabpanel\"]").filter((panel) => all(list, "[role=\"tab\"]").some((tab) => tab.getAttribute("aria-controls") === panel.id)).forEach((panel) => { + panel.hidden = panel.id !== tab.getAttribute("aria-controls"); + if (!panel.hidden && !panel.querySelector("a[href],button,input,select,textarea,[tabindex='0']")) panel.tabIndex = 0; + }); + if (focus) tab.focus(); + return tab; + }; + const activate = (tab) => { + select(tab.id); + root.emit("select", { + id: tab.id, + panelId: tab.getAttribute("aria-controls") + }); + }; + on(list, "click", (event) => { + const tab = event.target.closest("[role=\"tab\"]"); + if (tab && enabled(tab)) activate(tab); + }); + on(list, "keydown", (event) => { + const current = event.target.closest("[role=\"tab\"]"), options = items(); + if (!current) return; + const vertical = list.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(list).direction === "rtl"; + const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", previous = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; + let index = options.indexOf(current); + if (event.key === next) index++; + else if (event.key === previous) index--; + else if (event.key === "Home") index = 0; + else if (event.key === "End") index = options.length - 1; + else if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + activate(current); + return; + } else return; + event.preventDefault(); + const tab = rove(options, index); + if (root.getAttribute("activation") !== "manual") activate(tab); + }); + const initial = items().find((item) => item.getAttribute("aria-selected") === "true") ?? items()[0]; + if (initial) select(initial.id); + return { + select, + get selectedId() { + return list.querySelector("[aria-selected=\"true\"]")?.id ?? ""; + }, + set selectedId(id) { + select(id); + } + }; +} +function toolbar(root, { on }) { + const bar = root.querySelector("[role=\"toolbar\"]"); + if (!bar) return {}; + const controls = () => all(bar, "button,a[href],input,select").filter((node) => enabled(node) && visible(node) && !node.closest("[role=\"menu\"]")); + const initial = controls(); + rove(initial, Math.max(0, initial.findIndex((node) => node.tabIndex === 0)), false); + on(bar, "focusin", (event) => { + if (controls().includes(event.target)) rove(controls(), controls().indexOf(event.target), false); + }); + on(bar, "keydown", (event) => { + if (event.target.matches("input,select,textarea") || event.target.closest("[role=\"menu\"]")) return; + const items = controls(), index = items.indexOf(event.target); + const vertical = bar.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(bar).direction === "rtl"; + const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", prev = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; + if (![ + next, + prev, + "Home", + "End" + ].includes(event.key)) return; + event.preventDefault(); + rove(items, keyIndex({ + key: event.key, + index, + length: items.length, + next, + previous: prev + })); + }); + on(bar, "click", (event) => { + const button = event.target.closest("button[aria-pressed]"); + if (button && enabled(button)) { + button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + root.emit("action", { + action: button.dataset.action ?? button.textContent.trim(), + pressed: button.getAttribute("aria-pressed") === "true" + }); + } + }); + return {}; +} +function disclosure(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button[aria-controls][aria-expanded]"); + if (!button || !enabled(button)) return; + const target = root.querySelector(`#${CSS.escape(button.getAttribute("aria-controls"))}`); + if (!target) return; + const expanded = button.getAttribute("aria-expanded") !== "true"; + button.setAttribute("aria-expanded", String(expanded)); + target.hidden = !expanded; + root.emit("toggle", { + id: target.id, + expanded + }); + }); + const details = root.querySelector("details"); + on(details, "toggle", () => root.emit("toggle", { + id: details.id, + expanded: details.open + })); + return { + get open() { + return details?.open ?? false; + }, + set open(value) { + if (details) details.open = Boolean(value); + } + }; +} +function combobox(root, { on, signal }) { + const input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"); + if (!input || !list) return {}; + identify(root, list, "options"); + input.setAttribute("aria-controls", list.id); + let active = null, notifying = false; + const notify = () => { + notifying = true; + try { + nativeInput(input); + nativeInput(input, "change"); + } finally { + notifying = false; + } + }; + const options = () => all(list, "[role=\"option\"]").filter((node) => enabled(node) && !node.hidden && !node.closest("[role=\"group\"][hidden]")); + all(list, "[role=\"option\"]").forEach((option, index) => identify(root, option, `option-${index}`)); + const setActive = (option) => { + active = option; + all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); + if (option) { + input.setAttribute("aria-activedescendant", option.id); + option.scrollIntoView({ block: "nearest" }); + } else input.removeAttribute("aria-activedescendant"); + }; + const hide = () => { + list.hidden = true; + input.setAttribute("aria-expanded", "false"); + setActive(null); + }; + const filter = (query = input.value) => { + for (const option of all(list, "[role=\"option\"]")) if (enabled(option)) option.hidden = !option.textContent.toLocaleLowerCase().includes(query.toLocaleLowerCase()); + all(list, "[role=\"group\"]").forEach((group) => { + group.hidden = !all(group, "[role=\"option\"]").some((node) => enabled(node) && !node.hidden); + }); + const empty = root.querySelector(".combobox-empty"); + if (empty) { + empty.hidden = options().length !== 0; + empty.classList.toggle("combobox-empty-shown", !empty.hidden); + } + if (!options().includes(active)) setActive(null); + }; + const show = (allOptions = false) => { + if (!enabled(input) || input.readOnly) return; + filter(allOptions ? "" : input.value); + list.hidden = false; + input.setAttribute("aria-expanded", "true"); + place(input, list); + }; + const choose = (option) => { + if (!option || !enabled(option)) return; + input.value = option.dataset.value ?? option.textContent.trim(); + hide(); + notify(); + input.focus(); + }; + on(input, "input", () => { + if (!notifying) { + show(); + announce(root, `${options().length} options available.`); + } + }); + on(input, "keydown", (event) => { + if (event.key === "Tab") { + hide(); + return; + } + if (event.key === "Escape") { + if (!list.hidden) { + hide(); + event.stopPropagation(); + } else if (input.value) { + input.value = ""; + notify(); + event.stopPropagation(); + } + event.preventDefault(); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + hide(); + return; + } + if (["ArrowDown", "ArrowUp"].includes(event.key)) { + event.preventDefault(); + if (list.hidden) show(true); + if (event.altKey) return; + const items = options(), index = active ? items.indexOf(active) : event.key === "ArrowDown" ? -1 : 0; + if (items.length) setActive(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); + } else if (event.key === "Enter" && !list.hidden && active) { + event.preventDefault(); + choose(active); + } + }); + on(list, "pointerdown", (event) => { + if (event.target.closest("[role=\"option\"]")) event.preventDefault(); + }); + on(list, "click", (event) => choose(event.target.closest("[role=\"option\"]"))); + on(root.querySelector(".combobox-toggle"), "click", () => { + list.hidden ? show(true) : hide(); + input.focus(); + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!root.contains(event.target)) hide(); + }); + on(root, "focusout", () => queueMicrotask(() => { + if (!signal.aborted && !root.contains(root.ownerDocument.activeElement)) hide(); + })); + on(root.ownerDocument.defaultView, "resize", () => { + if (!list.hidden) place(input, list); + }); + on(root.ownerDocument, "scroll", (event) => { + if (!list.hidden && !list.contains(event.target)) place(input, list); + }, { capture: true }); + hide(); + return { + show, + hide, + get open() { + return !list.hidden; + }, + set open(value) { + value ? show() : hide(); + }, + get value() { + return input.value; + }, + set value(value) { + input.value = String(value ?? ""); + if (!list.hidden) filter(); + }, + cleanup: hide + }; +} +function menu(root, { on }) { + const trigger = root.querySelector("button[aria-haspopup=\"menu\"]"), main = root.querySelector("[role=\"menu\"]"); + if (!trigger || !main) return {}; + identify(root, main, "menu"); + trigger.setAttribute("aria-controls", main.id); + const lists = all(root, "[role=\"menu\"]"); + const items = (list) => all(list, "[role^=\"menuitem\"]").filter((item) => item.closest("[role=\"menu\"]") === list); + const controller = (list) => all(root, "[aria-controls]").find((node) => node.getAttribute("aria-controls") === list.id); + const closeList = (list) => { + list.hidden = true; + controller(list)?.setAttribute("aria-expanded", "false"); + }; + const hide = (focus = true) => { + lists.forEach(closeList); + if (focus) trigger.focus(); + }; + const showList = (list, button, last = false) => { + list.hidden = false; + button.setAttribute("aria-expanded", "true"); + place(button, list); + rove(items(list), last ? items(list).length - 1 : 0); + }; + const show = () => { + if (enabled(trigger)) showList(main, trigger); + }; + const submenu = (button) => button.hasAttribute("aria-haspopup") ? lists.find((list) => list.id === button.getAttribute("aria-controls")) : null; + const activate = (item) => { + if (!enabled(item)) return; + const child = submenu(item); + if (child) { + showList(child, item); + return; + } + if (item.getAttribute("role") === "menuitemcheckbox") item.setAttribute("aria-checked", String(item.getAttribute("aria-checked") !== "true")); + else if (item.getAttribute("role") === "menuitemradio") items(item.closest("[role=\"menu\"]")).filter((node) => node.getAttribute("role") === "menuitemradio").forEach((node) => node.setAttribute("aria-checked", String(node === item))); + else hide(); + root.emit("action", { + action: item.dataset.action ?? item.textContent.trim(), + checked: item.getAttribute("aria-checked") === "true" + }); + }; + on(trigger, "click", () => main.hidden ? show() : hide()); + on(trigger, "keydown", (event) => { + if (["ArrowDown", "ArrowUp"].includes(event.key) && enabled(trigger)) { + event.preventDefault(); + showList(main, trigger, event.key === "ArrowUp"); + } + }); + on(root, "click", (event) => { + const item = event.target.closest("[role^=\"menuitem\"]"); + if (item) activate(item); + }); + on(root, "keydown", (event) => { + const item = event.target.closest("[role^=\"menuitem\"]"); + if (!item) return; + const list = item.closest("[role=\"menu\"]"), options = items(list), index = options.indexOf(item), rtl = getComputedStyle(list).direction === "rtl"; + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + rove(options, keyIndex({ + key: event.key, + index, + length: options.length + })); + } else if (event.key === "Escape" || event.key === (rtl ? "ArrowRight" : "ArrowLeft") && list !== main) { + event.preventDefault(); + event.stopPropagation(); + if (list !== main) { + closeList(list); + controller(list)?.focus(); + } else hide(); + } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight") && submenu(item)) { + event.preventDefault(); + showList(submenu(item), item); + } else if (event.key === "Tab") hide(); + else if (event.key.length === 1 && /\S/.test(event.key)) { + const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(".menu-label") ?? node).textContent.trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); + if (found) { + event.preventDefault(); + rove(options, options.indexOf(found)); + } + } + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!root.contains(event.target)) hide(false); + }); + on(root.ownerDocument, "focusin", (event) => { + if (!root.contains(event.target)) hide(false); + }); + on(root.ownerDocument.defaultView, "resize", () => lists.filter((list) => !list.hidden).forEach((list) => place(controller(list), list))); + hide(false); + return { + show, + hide, + get open() { + return !main.hidden; + }, + set open(value) { + value ? show() : hide(false); + }, + cleanup() { + hide(false); + } + }; +} +export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/filterable-table/runtime/chunks/tables-Cjr1EIJz.js b/packages/ui/dist/copy/data-table/runtime/chunks/tables-zo8ebTOo.js similarity index 98% rename from packages/ui/dist/copy/filterable-table/runtime/chunks/tables-Cjr1EIJz.js rename to packages/ui/dist/copy/data-table/runtime/chunks/tables-zo8ebTOo.js index f82aaf25e..56f7f3dc3 100644 --- a/packages/ui/dist/copy/filterable-table/runtime/chunks/tables-Cjr1EIJz.js +++ b/packages/ui/dist/copy/data-table/runtime/chunks/tables-zo8ebTOo.js @@ -1,5 +1,5 @@ -import { c as keyIndex, f as rove, i as all, o as enabled, s as identify } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/tables.js +import { c as keyIndex, f as rove, i as all, o as enabled, s as identify } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/tables.js function table(root, { on }) { const element = root.querySelector("table"), body = element?.tBodies[0]; if (!element || !body) return {}; @@ -213,5 +213,4 @@ function pagination(root, { on }) { } }; } -//#endregion export { table as n, pagination as t }; diff --git a/packages/ui/dist/copy/data-table/runtime/components/data-table.js b/packages/ui/dist/copy/data-table/runtime/components/data-table.js index 2825525ad..cfd4a0614 100644 --- a/packages/ui/dist/copy/data-table/runtime/components/data-table.js +++ b/packages/ui/dist/copy/data-table/runtime/components/data-table.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as table } from "../chunks/tables-Cjr1EIJz.js"; -//#region .cache/ui-build/entries/components/data-table.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as table } from "../chunks/tables-zo8ebTOo.js"; +// .cache/ui-build/entries/components/data-table.js var J3w1DataTable = class extends J3w1Element { static componentId = "data-table"; static version = "4.0.0"; - static implementationId = "sha256-Qlh9cF0ylT3FE8z6iBYaA9/noI1T5dVrNgulqEfZGt8="; + static implementationId = "sha256-a/glnHoeWHm3aMAVgncz982T3PIGdFT6ck7ItsOxeDk="; static connect = table; static upgradeProperties = [ "disabled", @@ -32,5 +32,4 @@ var J3w1DataTable = class extends J3w1Element { }); } }; -//#endregion export { J3w1DataTable }; diff --git a/packages/ui/dist/copy/data-table/runtime/components/menu.js b/packages/ui/dist/copy/data-table/runtime/components/menu.js index b35ceb43e..b7031703c 100644 --- a/packages/ui/dist/copy/data-table/runtime/components/menu.js +++ b/packages/ui/dist/copy/data-table/runtime/components/menu.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as menu } from "../chunks/navigation-BfNzDYZB.js"; -//#region .cache/ui-build/entries/components/menu.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as menu } from "../chunks/navigation-CknoksQ5.js"; +// .cache/ui-build/entries/components/menu.js var J3w1Menu = class extends J3w1Element { static componentId = "menu"; static version = "4.0.0"; - static implementationId = "sha256-oS0Ubl9rLRKcmk22aO7KDARBpUoA/Y7sR2AvyqabH+U="; + static implementationId = "sha256-eK7xkdMDWtplCwL1L9Yt83xHvFQIuO3z1yoixK4RXOo="; static connect = menu; static upgradeProperties = [ "disabled", @@ -32,5 +32,4 @@ var J3w1Menu = class extends J3w1Element { }); } }; -//#endregion export { J3w1Menu }; diff --git a/packages/ui/dist/copy/data-table/runtime/register/data-table.js b/packages/ui/dist/copy/data-table/runtime/register/data-table.js index 4d622c48b..b84bc8231 100644 --- a/packages/ui/dist/copy/data-table/runtime/register/data-table.js +++ b/packages/ui/dist/copy/data-table/runtime/register/data-table.js @@ -1,7 +1,6 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import "./menu.js"; import { J3w1DataTable } from "../components/data-table.js"; -//#region .cache/ui-build/entries/register/data-table.js +// .cache/ui-build/entries/register/data-table.js var element = registerElement("j3w1-data-table", J3w1DataTable); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/data-table/runtime/register/menu.js b/packages/ui/dist/copy/data-table/runtime/register/menu.js index 655b77a5a..e99b1d3df 100644 --- a/packages/ui/dist/copy/data-table/runtime/register/menu.js +++ b/packages/ui/dist/copy/data-table/runtime/register/menu.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Menu } from "../components/menu.js"; -//#region .cache/ui-build/entries/register/menu.js +// .cache/ui-build/entries/register/menu.js var element = registerElement("j3w1-menu", J3w1Menu); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/date-picker/manifest.json b/packages/ui/dist/copy/date-picker/manifest.json index 0a00e671d..595cf0965 100644 --- a/packages/ui/dist/copy/date-picker/manifest.json +++ b/packages/ui/dist/copy/date-picker/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/date-picker.md", "dependencies": [ "register/date-picker.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/date-picker.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/date-picker.js": "sha256-ffEEGjAUrXQXzVdMaSM5DtzrLavfYTdLxmkWhPWQRIo=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/date-picker.js": "sha256-6V4hlflxeVpDoj+uuaVEpTKm1ZKIyCYAiivLhpESyZU=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/date-picker.js": "sha256-2QI9scZ50FCzd1DsWatvh7W1DIyTKZ5FhrKPs84ihDM=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/date-picker.js": "sha256-rrcEetO6fITkbc8adFGTiWLPMv6dMJt7S3emImwYDZg=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-17l8tm/NKV8wNhq8EIPnmw9/+K4egrcSbiuLY63EpUs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/date-picker/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/date-picker/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/date-picker/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/date-picker/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/date-picker/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/date-picker/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/date-picker/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/date-picker/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/date-picker/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/date-picker/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/date-picker/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/date-picker/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/date-picker/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/date-picker/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/date-picker/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/date-picker/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/date-picker/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/date-picker/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/date-picker/runtime/components/date-picker.js b/packages/ui/dist/copy/date-picker/runtime/components/date-picker.js index df35db9b0..8a93fcbc4 100644 --- a/packages/ui/dist/copy/date-picker/runtime/components/date-picker.js +++ b/packages/ui/dist/copy/date-picker/runtime/components/date-picker.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/date-picker.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/date-picker.js var J3w1DatePicker = class extends J3w1Element { static componentId = "date-picker"; static version = "4.0.0"; - static implementationId = "sha256-rz3at5sJTA4TkXHNaqQnM5BrVBt02my29UyKewvFuRY="; + static implementationId = "sha256-kmW88a2eETKKePSXhvndNd/jUUTZa5oQ4kDsL8OPCK0="; static connect = fields; static upgradeProperties = [ "disabled", @@ -27,5 +27,4 @@ var J3w1DatePicker = class extends J3w1Element { return this._api.clear(...args); } }; -//#endregion export { J3w1DatePicker }; diff --git a/packages/ui/dist/copy/date-picker/runtime/register/date-picker.js b/packages/ui/dist/copy/date-picker/runtime/register/date-picker.js index 541cd14fa..99d27ba70 100644 --- a/packages/ui/dist/copy/date-picker/runtime/register/date-picker.js +++ b/packages/ui/dist/copy/date-picker/runtime/register/date-picker.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1DatePicker } from "../components/date-picker.js"; -//#region .cache/ui-build/entries/register/date-picker.js +// .cache/ui-build/entries/register/date-picker.js var element = registerElement("j3w1-date-picker", J3w1DatePicker); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/description-list/manifest.json b/packages/ui/dist/copy/description-list/manifest.json index 03fdfd104..01045ab72 100644 --- a/packages/ui/dist/copy/description-list/manifest.json +++ b/packages/ui/dist/copy/description-list/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/description-list.md", "dependencies": [ "register/description-list.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/description-list.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/description-list.js": "sha256-GxP5SJuhMhu1hTHJsexrOw4T0UPxiW6YpB5Ekig6NG4=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/description-list.js": "sha256-yFwjohrGKRZXL7ylzdMxau2tHWLBEqlCrjhZFLoV5ms=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/description-list.js": "sha256-3osvUC9RVQ+Zm7/LnA1QxjmPZY3uAc+I2yqkHiwsBxY=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/description-list.js": "sha256-n1agfwnHxoAp1znriJX4mVEszfKtm0Hwyy9AYRVRbkg=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-rEMzb+R626s/u4B9UVumgQsD0pKkWBBP5+VSfJrPCLM=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/description-list/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/description-list/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/description-list/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/description-list/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/description-list/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/description-list/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/description-list/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/description-list/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/description-list/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/description-list/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/description-list/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/description-list/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/description-list/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/description-list/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/description-list/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/description-list/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/description-list/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/description-list/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/description-list/runtime/components/description-list.js b/packages/ui/dist/copy/description-list/runtime/components/description-list.js index f7a7090ba..162d0cd1c 100644 --- a/packages/ui/dist/copy/description-list/runtime/components/description-list.js +++ b/packages/ui/dist/copy/description-list/runtime/components/description-list.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/description-list.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/description-list.js var J3w1DescriptionList = class extends J3w1Element { static componentId = "description-list"; static version = "4.0.0"; - static implementationId = "sha256-O3lqE1mNupuyqMqz1k1EzRDHMDjwD6aUReeED7JUclg="; + static implementationId = "sha256-DDcuNke+fAkSGnaDiAAucdChnaJzCXZYRFzSpYvEy5g="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1DescriptionList }; diff --git a/packages/ui/dist/copy/description-list/runtime/register/description-list.js b/packages/ui/dist/copy/description-list/runtime/register/description-list.js index 37a62a7a6..b94beeffe 100644 --- a/packages/ui/dist/copy/description-list/runtime/register/description-list.js +++ b/packages/ui/dist/copy/description-list/runtime/register/description-list.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1DescriptionList } from "../components/description-list.js"; -//#region .cache/ui-build/entries/register/description-list.js +// .cache/ui-build/entries/register/description-list.js var element = registerElement("j3w1-description-list", J3w1DescriptionList); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/diagnostics/manifest.json b/packages/ui/dist/copy/diagnostics/manifest.json index 618e5267a..872998592 100644 --- a/packages/ui/dist/copy/diagnostics/manifest.json +++ b/packages/ui/dist/copy/diagnostics/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/diagnostics.md", "dependencies": [ "register/diagnostics.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/diagnostics.js", - "chunks/display-Jm9bAsnb.js" + "chunks/display-l54fb8vw.js" ], "files": { - "runtime/register/diagnostics.js": "sha256-ALvK2a/RKv8dPsd7vtPOz2gs07sAqHYUeaLkBGbL2bQ=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/diagnostics.js": "sha256-oEE2P+tyCuYFS8Z67kakU24ozr9nPJsXvN7ug/nsESs=", - "runtime/chunks/display-Jm9bAsnb.js": "sha256-qZb1g04piEwY3lfFJwMe+0mXR218ljtVi8mepWxrFv8=", + "runtime/register/diagnostics.js": "sha256-hjSy+H8Mj1uBgwhB3c/KjtBkY7xJnYXTSeLGJM0xvdU=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/diagnostics.js": "sha256-QBQTzBXbzspprSZunB6lifyi7iGa8PykXE4Qvmdc+mI=", + "runtime/chunks/display-l54fb8vw.js": "sha256-xfzo614uMLlSbZc5l+o4vHvrL8yBjQAcV/HJdmPUJ/g=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-xWB/G9X0gadCbFJ8yqKBaXbBvMPSKyKrVUQR4dZZs88=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/diagnostics/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/diagnostics/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/diagnostics/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/diagnostics/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/diagnostics/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/diagnostics/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/diagnostics/runtime/chunks/display-Jm9bAsnb.js b/packages/ui/dist/copy/diagnostics/runtime/chunks/display-Jm9bAsnb.js deleted file mode 100644 index 5bc817830..000000000 --- a/packages/ui/dist/copy/diagnostics/runtime/chunks/display-Jm9bAsnb.js +++ /dev/null @@ -1,212 +0,0 @@ -import { i as all, l as make, o as enabled } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/display.js -function avatar(root, { on }) { - const frame = root.querySelector(".avatar"), fallback = root.querySelector("[data-avatar-fallback]"); - if (!frame || !fallback) return {}; - let image = frame.querySelector("img"); - if (!image) { - image = make(root, "img", { - alt: "", - hidden: "" - }); - frame.prepend(image); - } - let source = image.getAttribute("src") ?? ""; - const update = (value) => { - source = String(value ?? ""); - image.hidden = true; - fallback.hidden = false; - delete frame.dataset.error; - if (!source) { - image.removeAttribute("src"); - delete frame.dataset.loading; - return; - } - frame.dataset.loading = "true"; - image.src = source; - }; - on(image, "load", () => { - delete frame.dataset.loading; - image.hidden = false; - fallback.hidden = true; - }); - on(image, "error", () => { - delete frame.dataset.loading; - frame.dataset.error = "true"; - image.hidden = true; - fallback.hidden = false; - }); - update(root.getAttribute("src") ?? source); - return { - get src() { - return source; - }, - set src(value) { - update(value); - }, - attributeChanged(name) { - if (name === "src") update(root.getAttribute("src")); - } - }; -} -function chart(root) { - const figure = root.querySelector("figure"), svg = figure?.querySelector("svg"), tbody = figure?.querySelector("tbody"); - if (!figure || !svg || !tbody) return {}; - let values = all(tbody, "tr").map((row) => ({ - label: row.cells[0]?.textContent.trim() ?? "", - value: Number(row.cells[1]?.textContent) - })); - const update = (data) => { - if (!Array.isArray(data) || data.length > 200 || data.some((row) => typeof row.label !== "string" || typeof row.value !== "number" || !Number.isFinite(row.value) || row.value < 0)) throw new TypeError("data must contain at most 200 labelled finite non-negative values"); - values = data.map((row) => ({ - label: row.label, - value: row.value - })); - svg.replaceChildren(); - tbody.replaceChildren(); - const ns = "http://www.w3.org/2000/svg"; - const group = root.ownerDocument.createElementNS(ns, "g"); - group.setAttribute("class", "chart-series"); - svg.append(group); - const width = Math.max(300, values.length * 32), max = Math.max(1, ...values.map((row) => row.value)); - svg.setAttribute("viewBox", `0 0 ${width} 140`); - svg.setAttribute("aria-label", values.length ? values.map((row) => `${row.label}: ${row.value}`).join("; ") : "No data available"); - for (const [index, row] of values.entries()) { - const bar = root.ownerDocument.createElementNS(ns, "rect"), step = (width - 20) / values.length, height = row.value / max * 100; - for (const [name, value] of Object.entries({ - x: 10 + index * step + step * .15, - y: 110 - height, - width: step * .7, - height - })) bar.setAttribute(name, String(value)); - const title = root.ownerDocument.createElementNS(ns, "title"); - title.textContent = `${row.label}: ${row.value}`; - bar.append(title); - group.append(bar); - const tr = make(root, "tr"); - tr.append(make(root, "th", { scope: "row" }, row.label), make(root, "td", {}, row.value)); - tbody.append(tr); - } - svg.toggleAttribute("hidden", !values.length); - const empty = figure.querySelector("[data-chart-empty]"); - if (empty) empty.hidden = values.length !== 0; - }; - return { - get data() { - return values.map((row) => ({ ...row })); - }, - set data(data) { - update(data); - } - }; -} -function editorSearch(root, { on }) { - const input = root.querySelector("[data-query]"), pre = root.querySelector("[data-source]"), status = root.querySelector("[data-search-status]"); - if (!input || !pre) return {}; - let source = pre.textContent, current = -1, matches = []; - const previous = root.querySelector("[data-previous]"), following = root.querySelector("[data-next]"); - const select = (index) => { - current = matches.length ? (index + matches.length) % matches.length : -1; - all(pre, "mark").forEach((mark, i) => mark.toggleAttribute("data-current", i === current)); - if (status) status.textContent = !input.value ? "Enter text to search." : matches.length ? `Match ${current + 1} of ${matches.length}` : "No matches."; - }; - const search = () => { - matches = []; - pre.replaceChildren(); - const query = input.value.toLocaleLowerCase(); - let folded = "", offset = 0; - const starts = [], ends = []; - for (const char of source) { - const text = char.toLocaleLowerCase(); - for (let i = 0; i < text.length; i++) { - starts.push(offset); - ends.push(offset + char.length); - } - folded += text; - offset += char.length; - } - if (query) { - let position = 0; - while ((position = folded.indexOf(query, position)) >= 0) { - const start = starts[position], end = ends[position + query.length - 1]; - if (!matches.length || start >= matches.at(-1).end) matches.push({ - start, - end - }); - position += query.length; - } - } - let cursor = 0; - for (const match of matches) { - pre.append(root.ownerDocument.createTextNode(source.slice(cursor, match.start)), make(root, "mark", {}, source.slice(match.start, match.end))); - cursor = match.end; - } - pre.append(root.ownerDocument.createTextNode(source.slice(cursor))); - if (previous) previous.disabled = !matches.length; - if (following) following.disabled = !matches.length; - select(0); - }; - const next = (direction = 1) => { - if (!matches.length) return; - select(current + (direction < 0 ? -1 : 1)); - all(pre, "mark")[current]?.scrollIntoView({ - block: "nearest", - inline: "nearest" - }); - }; - on(input, "input", search); - on(input, "keydown", (event) => { - if (event.key === "Enter") { - event.preventDefault(); - next(event.shiftKey ? -1 : 1); - } else if (event.key === "Escape" && input.value) { - event.preventDefault(); - event.stopPropagation(); - input.value = ""; - search(); - } - }); - on(previous, "click", () => next(-1)); - on(following, "click", () => next()); - search(); - return { - next, - get source() { - return source; - }, - set source(text) { - source = String(text); - search(); - }, - get query() { - return input.value; - }, - set query(value) { - input.value = String(value); - search(); - }, - get matchCount() { - return matches.length; - } - }; -} -function developerView(root, { on }) { - on(root, "click", (event) => { - const action = event.target.closest("button,[data-action]"); - if (action && enabled(action)) root.emit("action", { action: action.dataset.action ?? action.textContent.trim() }); - }); - return { setText(text) { - let pre = root.querySelector("pre"); - if (!pre) { - pre = make(root, "pre", { - class: "j3w1-readonly-text", - tabindex: "0", - "aria-label": "Read-only text" - }); - root.firstElementChild.replaceChildren(pre); - } - pre.textContent = String(text); - } }; -} -//#endregion -export { editorSearch as i, chart as n, developerView as r, avatar as t }; diff --git a/packages/ui/dist/copy/diagnostics/runtime/chunks/display-l54fb8vw.js b/packages/ui/dist/copy/diagnostics/runtime/chunks/display-l54fb8vw.js new file mode 100644 index 000000000..b2f57aaf2 --- /dev/null +++ b/packages/ui/dist/copy/diagnostics/runtime/chunks/display-l54fb8vw.js @@ -0,0 +1,211 @@ +import { i as all, l as make, o as enabled } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/display.js +function avatar(root, { on }) { + const frame = root.querySelector(".avatar"), fallback = root.querySelector("[data-avatar-fallback]"); + if (!frame || !fallback) return {}; + let image = frame.querySelector("img"); + if (!image) { + image = make(root, "img", { + alt: "", + hidden: "" + }); + frame.prepend(image); + } + let source = image.getAttribute("src") ?? ""; + const update = (value) => { + source = String(value ?? ""); + image.hidden = true; + fallback.hidden = false; + delete frame.dataset.error; + if (!source) { + image.removeAttribute("src"); + delete frame.dataset.loading; + return; + } + frame.dataset.loading = "true"; + image.src = source; + }; + on(image, "load", () => { + delete frame.dataset.loading; + image.hidden = false; + fallback.hidden = true; + }); + on(image, "error", () => { + delete frame.dataset.loading; + frame.dataset.error = "true"; + image.hidden = true; + fallback.hidden = false; + }); + update(root.getAttribute("src") ?? source); + return { + get src() { + return source; + }, + set src(value) { + update(value); + }, + attributeChanged(name) { + if (name === "src") update(root.getAttribute("src")); + } + }; +} +function chart(root) { + const figure = root.querySelector("figure"), svg = figure?.querySelector("svg"), tbody = figure?.querySelector("tbody"); + if (!figure || !svg || !tbody) return {}; + let values = all(tbody, "tr").map((row) => ({ + label: row.cells[0]?.textContent.trim() ?? "", + value: Number(row.cells[1]?.textContent) + })); + const update = (data) => { + if (!Array.isArray(data) || data.length > 200 || data.some((row) => typeof row.label !== "string" || typeof row.value !== "number" || !Number.isFinite(row.value) || row.value < 0)) throw new TypeError("data must contain at most 200 labelled finite non-negative values"); + values = data.map((row) => ({ + label: row.label, + value: row.value + })); + svg.replaceChildren(); + tbody.replaceChildren(); + const ns = "http://www.w3.org/2000/svg"; + const group = root.ownerDocument.createElementNS(ns, "g"); + group.setAttribute("class", "chart-series"); + svg.append(group); + const width = Math.max(300, values.length * 32), max = Math.max(1, ...values.map((row) => row.value)); + svg.setAttribute("viewBox", `0 0 ${width} 140`); + svg.setAttribute("aria-label", values.length ? values.map((row) => `${row.label}: ${row.value}`).join("; ") : "No data available"); + for (const [index, row] of values.entries()) { + const bar = root.ownerDocument.createElementNS(ns, "rect"), step = (width - 20) / values.length, height = row.value / max * 100; + for (const [name, value] of Object.entries({ + x: 10 + index * step + step * .15, + y: 110 - height, + width: step * .7, + height + })) bar.setAttribute(name, String(value)); + const title = root.ownerDocument.createElementNS(ns, "title"); + title.textContent = `${row.label}: ${row.value}`; + bar.append(title); + group.append(bar); + const tr = make(root, "tr"); + tr.append(make(root, "th", { scope: "row" }, row.label), make(root, "td", {}, row.value)); + tbody.append(tr); + } + svg.toggleAttribute("hidden", !values.length); + const empty = figure.querySelector("[data-chart-empty]"); + if (empty) empty.hidden = values.length !== 0; + }; + return { + get data() { + return values.map((row) => ({ ...row })); + }, + set data(data) { + update(data); + } + }; +} +function editorSearch(root, { on }) { + const input = root.querySelector("[data-query]"), pre = root.querySelector("[data-source]"), status = root.querySelector("[data-search-status]"); + if (!input || !pre) return {}; + let source = pre.textContent, current = -1, matches = []; + const previous = root.querySelector("[data-previous]"), following = root.querySelector("[data-next]"); + const select = (index) => { + current = matches.length ? (index + matches.length) % matches.length : -1; + all(pre, "mark").forEach((mark, i) => mark.toggleAttribute("data-current", i === current)); + if (status) status.textContent = !input.value ? "Enter text to search." : matches.length ? `Match ${current + 1} of ${matches.length}` : "No matches."; + }; + const search = () => { + matches = []; + pre.replaceChildren(); + const query = input.value.toLocaleLowerCase(); + let folded = "", offset = 0; + const starts = [], ends = []; + for (const char of source) { + const text = char.toLocaleLowerCase(); + for (let i = 0; i < text.length; i++) { + starts.push(offset); + ends.push(offset + char.length); + } + folded += text; + offset += char.length; + } + if (query) { + let position = 0; + while ((position = folded.indexOf(query, position)) >= 0) { + const start = starts[position], end = ends[position + query.length - 1]; + if (!matches.length || start >= matches.at(-1).end) matches.push({ + start, + end + }); + position += query.length; + } + } + let cursor = 0; + for (const match of matches) { + pre.append(root.ownerDocument.createTextNode(source.slice(cursor, match.start)), make(root, "mark", {}, source.slice(match.start, match.end))); + cursor = match.end; + } + pre.append(root.ownerDocument.createTextNode(source.slice(cursor))); + if (previous) previous.disabled = !matches.length; + if (following) following.disabled = !matches.length; + select(0); + }; + const next = (direction = 1) => { + if (!matches.length) return; + select(current + (direction < 0 ? -1 : 1)); + all(pre, "mark")[current]?.scrollIntoView({ + block: "nearest", + inline: "nearest" + }); + }; + on(input, "input", search); + on(input, "keydown", (event) => { + if (event.key === "Enter") { + event.preventDefault(); + next(event.shiftKey ? -1 : 1); + } else if (event.key === "Escape" && input.value) { + event.preventDefault(); + event.stopPropagation(); + input.value = ""; + search(); + } + }); + on(previous, "click", () => next(-1)); + on(following, "click", () => next()); + search(); + return { + next, + get source() { + return source; + }, + set source(text) { + source = String(text); + search(); + }, + get query() { + return input.value; + }, + set query(value) { + input.value = String(value); + search(); + }, + get matchCount() { + return matches.length; + } + }; +} +function developerView(root, { on }) { + on(root, "click", (event) => { + const action = event.target.closest("button,[data-action]"); + if (action && enabled(action)) root.emit("action", { action: action.dataset.action ?? action.textContent.trim() }); + }); + return { setText(text) { + let pre = root.querySelector("pre"); + if (!pre) { + pre = make(root, "pre", { + class: "j3w1-readonly-text", + tabindex: "0", + "aria-label": "Read-only text" + }); + root.firstElementChild.replaceChildren(pre); + } + pre.textContent = String(text); + } }; +} +export { editorSearch as i, chart as n, developerView as r, avatar as t }; diff --git a/packages/ui/dist/copy/diagnostics/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/diagnostics/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/diagnostics/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/diagnostics/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/diagnostics/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/diagnostics/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/diagnostics/runtime/components/diagnostics.js b/packages/ui/dist/copy/diagnostics/runtime/components/diagnostics.js index f9e49175b..c59d7464f 100644 --- a/packages/ui/dist/copy/diagnostics/runtime/components/diagnostics.js +++ b/packages/ui/dist/copy/diagnostics/runtime/components/diagnostics.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as developerView } from "../chunks/display-Jm9bAsnb.js"; -//#region .cache/ui-build/entries/components/diagnostics.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as developerView } from "../chunks/display-l54fb8vw.js"; +// .cache/ui-build/entries/components/diagnostics.js var J3w1Diagnostics = class extends J3w1Element { static componentId = "diagnostics"; static version = "4.0.0"; - static implementationId = "sha256-lcf+xRikFjf+LQY6YZN+giWDauQWjFZbMz3xBLI3JG8="; + static implementationId = "sha256-Mh5W9ln8UtoAd11LHTHBFeXEbEIbq3SsLr4Dp7ETLtk="; static connect = developerView; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -13,5 +13,4 @@ var J3w1Diagnostics = class extends J3w1Element { return this._api.setText(...args); } }; -//#endregion export { J3w1Diagnostics }; diff --git a/packages/ui/dist/copy/diagnostics/runtime/register/diagnostics.js b/packages/ui/dist/copy/diagnostics/runtime/register/diagnostics.js index 2d9f84547..46854f8ab 100644 --- a/packages/ui/dist/copy/diagnostics/runtime/register/diagnostics.js +++ b/packages/ui/dist/copy/diagnostics/runtime/register/diagnostics.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Diagnostics } from "../components/diagnostics.js"; -//#region .cache/ui-build/entries/register/diagnostics.js +// .cache/ui-build/entries/register/diagnostics.js var element = registerElement("j3w1-diagnostics", J3w1Diagnostics); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/dialog/manifest.json b/packages/ui/dist/copy/dialog/manifest.json index 36badeeb1..b62e9c7db 100644 --- a/packages/ui/dist/copy/dialog/manifest.json +++ b/packages/ui/dist/copy/dialog/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/dialog.md", "dependencies": [ "register/dialog.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/dialog.js", - "chunks/overlays-BwgpF4jI.js" + "chunks/overlays-BW66WXLm.js" ], "files": { - "runtime/register/dialog.js": "sha256-waqEj5W9GRcvFu/OpnJxmONEY3yiBYgB2Fak5uwMsbA=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/dialog.js": "sha256-zdWNMLxqa07G4DrP8cSpEYY3F05kRGbx8cg0OGyNzbE=", - "runtime/chunks/overlays-BwgpF4jI.js": "sha256-NAd99OT4kDsFp8IHscKRus2jY6XRsq+GMzplWbJsY4U=", + "runtime/register/dialog.js": "sha256-JEbzrKsC4vP0ZdqSOolILA3NQuVhOa+XZoXfduM+PAI=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/dialog.js": "sha256-Bwsz1OfbAchVk6TFl8egez6a03B4iopAkl0edtrHcPs=", + "runtime/chunks/overlays-BW66WXLm.js": "sha256-Z9etmUpuDuykKbJkriLMz8iiYnOP9uMUAshKwoHc1I8=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-PL+Ntvoc1uooINO+TPwR7KzuU7dbER2pJdlz10y0UyY=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/dialog/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/dialog/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/dialog/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/dialog/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/dialog/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/dialog/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/dialog/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/dialog/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/dialog/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/dialog/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/dialog/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/dialog/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/chunks/overlays-BwgpF4jI.js b/packages/ui/dist/copy/dialog/runtime/chunks/overlays-BW66WXLm.js similarity index 98% rename from packages/ui/dist/chunks/overlays-BwgpF4jI.js rename to packages/ui/dist/copy/dialog/runtime/chunks/overlays-BW66WXLm.js index 4b8de2e8b..d05c73b46 100644 --- a/packages/ui/dist/chunks/overlays-BwgpF4jI.js +++ b/packages/ui/dist/copy/dialog/runtime/chunks/overlays-BW66WXLm.js @@ -1,5 +1,5 @@ -import { d as place, i as all, o as enabled, s as identify } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/overlays.js +import { d as place, i as all, o as enabled, s as identify } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/overlays.js function modal(root, { on }) { const dialog = root.querySelector("dialog"); if (!dialog) return {}; @@ -241,5 +241,4 @@ function feedback(root, { on }) { dismiss(id ? root.querySelector(`#${CSS.escape(id)}`) : root.querySelector(".toast,.alert") ?? root); } }; } -//#endregion export { tooltip as i, modal as n, popover as r, feedback as t }; diff --git a/packages/ui/dist/copy/dialog/runtime/components/dialog.js b/packages/ui/dist/copy/dialog/runtime/components/dialog.js index 3cbfc19af..f8cb9f4ed 100644 --- a/packages/ui/dist/copy/dialog/runtime/components/dialog.js +++ b/packages/ui/dist/copy/dialog/runtime/components/dialog.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as modal } from "../chunks/overlays-BwgpF4jI.js"; -//#region .cache/ui-build/entries/components/dialog.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as modal } from "../chunks/overlays-BW66WXLm.js"; +// .cache/ui-build/entries/components/dialog.js var J3w1Dialog = class extends J3w1Element { static componentId = "dialog"; static version = "4.0.0"; - static implementationId = "sha256-DxVkWaABviJy7mGLL8EMH80qBAY41vg1uSdV+1wlXPw="; + static implementationId = "sha256-y5bLLW2MSsvkA0D+5dWrD70gQejnbCLVcva+Y0egKag="; static connect = modal; static upgradeProperties = [ "disabled", @@ -35,5 +35,4 @@ var J3w1Dialog = class extends J3w1Element { return this._api?.returnValue; } }; -//#endregion export { J3w1Dialog }; diff --git a/packages/ui/dist/copy/dialog/runtime/register/dialog.js b/packages/ui/dist/copy/dialog/runtime/register/dialog.js index bded0a66c..5dcb6a328 100644 --- a/packages/ui/dist/copy/dialog/runtime/register/dialog.js +++ b/packages/ui/dist/copy/dialog/runtime/register/dialog.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Dialog } from "../components/dialog.js"; -//#region .cache/ui-build/entries/register/dialog.js +// .cache/ui-build/entries/register/dialog.js var element = registerElement("j3w1-dialog", J3w1Dialog); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/diff-view/manifest.json b/packages/ui/dist/copy/diff-view/manifest.json index 1d9229575..f1b85aa9a 100644 --- a/packages/ui/dist/copy/diff-view/manifest.json +++ b/packages/ui/dist/copy/diff-view/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/diff-view.md", "dependencies": [ "register/diff-view.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/diff-view.js", - "chunks/display-Jm9bAsnb.js" + "chunks/display-l54fb8vw.js" ], "files": { - "runtime/register/diff-view.js": "sha256-9TubYFM9ksBHugPVTEwpyuq1pqPeA3BwnBpoJdM5zRE=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/diff-view.js": "sha256-mc+zZLXtFDZnF4okQ840vLAw4mC40kkmR920bUXfXfo=", - "runtime/chunks/display-Jm9bAsnb.js": "sha256-qZb1g04piEwY3lfFJwMe+0mXR218ljtVi8mepWxrFv8=", + "runtime/register/diff-view.js": "sha256-BsyD+ZpxaLT5ZiaNNhFmNuMdqFMWiOTd9cR6DViCLm0=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/diff-view.js": "sha256-ZypShgLxT+vpLJpO7zGyps5bBAEEyS3zxyCDCxJvz+I=", + "runtime/chunks/display-l54fb8vw.js": "sha256-xfzo614uMLlSbZc5l+o4vHvrL8yBjQAcV/HJdmPUJ/g=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-zQ+2X33S+1rlKgj8VvnNJSfS/ujlxlYAFFAC3vC+8MU=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/diff-view/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/diff-view/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/diff-view/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/diff-view/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/diff-view/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/diff-view/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/diff-view/runtime/chunks/display-Jm9bAsnb.js b/packages/ui/dist/copy/diff-view/runtime/chunks/display-Jm9bAsnb.js deleted file mode 100644 index 5bc817830..000000000 --- a/packages/ui/dist/copy/diff-view/runtime/chunks/display-Jm9bAsnb.js +++ /dev/null @@ -1,212 +0,0 @@ -import { i as all, l as make, o as enabled } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/display.js -function avatar(root, { on }) { - const frame = root.querySelector(".avatar"), fallback = root.querySelector("[data-avatar-fallback]"); - if (!frame || !fallback) return {}; - let image = frame.querySelector("img"); - if (!image) { - image = make(root, "img", { - alt: "", - hidden: "" - }); - frame.prepend(image); - } - let source = image.getAttribute("src") ?? ""; - const update = (value) => { - source = String(value ?? ""); - image.hidden = true; - fallback.hidden = false; - delete frame.dataset.error; - if (!source) { - image.removeAttribute("src"); - delete frame.dataset.loading; - return; - } - frame.dataset.loading = "true"; - image.src = source; - }; - on(image, "load", () => { - delete frame.dataset.loading; - image.hidden = false; - fallback.hidden = true; - }); - on(image, "error", () => { - delete frame.dataset.loading; - frame.dataset.error = "true"; - image.hidden = true; - fallback.hidden = false; - }); - update(root.getAttribute("src") ?? source); - return { - get src() { - return source; - }, - set src(value) { - update(value); - }, - attributeChanged(name) { - if (name === "src") update(root.getAttribute("src")); - } - }; -} -function chart(root) { - const figure = root.querySelector("figure"), svg = figure?.querySelector("svg"), tbody = figure?.querySelector("tbody"); - if (!figure || !svg || !tbody) return {}; - let values = all(tbody, "tr").map((row) => ({ - label: row.cells[0]?.textContent.trim() ?? "", - value: Number(row.cells[1]?.textContent) - })); - const update = (data) => { - if (!Array.isArray(data) || data.length > 200 || data.some((row) => typeof row.label !== "string" || typeof row.value !== "number" || !Number.isFinite(row.value) || row.value < 0)) throw new TypeError("data must contain at most 200 labelled finite non-negative values"); - values = data.map((row) => ({ - label: row.label, - value: row.value - })); - svg.replaceChildren(); - tbody.replaceChildren(); - const ns = "http://www.w3.org/2000/svg"; - const group = root.ownerDocument.createElementNS(ns, "g"); - group.setAttribute("class", "chart-series"); - svg.append(group); - const width = Math.max(300, values.length * 32), max = Math.max(1, ...values.map((row) => row.value)); - svg.setAttribute("viewBox", `0 0 ${width} 140`); - svg.setAttribute("aria-label", values.length ? values.map((row) => `${row.label}: ${row.value}`).join("; ") : "No data available"); - for (const [index, row] of values.entries()) { - const bar = root.ownerDocument.createElementNS(ns, "rect"), step = (width - 20) / values.length, height = row.value / max * 100; - for (const [name, value] of Object.entries({ - x: 10 + index * step + step * .15, - y: 110 - height, - width: step * .7, - height - })) bar.setAttribute(name, String(value)); - const title = root.ownerDocument.createElementNS(ns, "title"); - title.textContent = `${row.label}: ${row.value}`; - bar.append(title); - group.append(bar); - const tr = make(root, "tr"); - tr.append(make(root, "th", { scope: "row" }, row.label), make(root, "td", {}, row.value)); - tbody.append(tr); - } - svg.toggleAttribute("hidden", !values.length); - const empty = figure.querySelector("[data-chart-empty]"); - if (empty) empty.hidden = values.length !== 0; - }; - return { - get data() { - return values.map((row) => ({ ...row })); - }, - set data(data) { - update(data); - } - }; -} -function editorSearch(root, { on }) { - const input = root.querySelector("[data-query]"), pre = root.querySelector("[data-source]"), status = root.querySelector("[data-search-status]"); - if (!input || !pre) return {}; - let source = pre.textContent, current = -1, matches = []; - const previous = root.querySelector("[data-previous]"), following = root.querySelector("[data-next]"); - const select = (index) => { - current = matches.length ? (index + matches.length) % matches.length : -1; - all(pre, "mark").forEach((mark, i) => mark.toggleAttribute("data-current", i === current)); - if (status) status.textContent = !input.value ? "Enter text to search." : matches.length ? `Match ${current + 1} of ${matches.length}` : "No matches."; - }; - const search = () => { - matches = []; - pre.replaceChildren(); - const query = input.value.toLocaleLowerCase(); - let folded = "", offset = 0; - const starts = [], ends = []; - for (const char of source) { - const text = char.toLocaleLowerCase(); - for (let i = 0; i < text.length; i++) { - starts.push(offset); - ends.push(offset + char.length); - } - folded += text; - offset += char.length; - } - if (query) { - let position = 0; - while ((position = folded.indexOf(query, position)) >= 0) { - const start = starts[position], end = ends[position + query.length - 1]; - if (!matches.length || start >= matches.at(-1).end) matches.push({ - start, - end - }); - position += query.length; - } - } - let cursor = 0; - for (const match of matches) { - pre.append(root.ownerDocument.createTextNode(source.slice(cursor, match.start)), make(root, "mark", {}, source.slice(match.start, match.end))); - cursor = match.end; - } - pre.append(root.ownerDocument.createTextNode(source.slice(cursor))); - if (previous) previous.disabled = !matches.length; - if (following) following.disabled = !matches.length; - select(0); - }; - const next = (direction = 1) => { - if (!matches.length) return; - select(current + (direction < 0 ? -1 : 1)); - all(pre, "mark")[current]?.scrollIntoView({ - block: "nearest", - inline: "nearest" - }); - }; - on(input, "input", search); - on(input, "keydown", (event) => { - if (event.key === "Enter") { - event.preventDefault(); - next(event.shiftKey ? -1 : 1); - } else if (event.key === "Escape" && input.value) { - event.preventDefault(); - event.stopPropagation(); - input.value = ""; - search(); - } - }); - on(previous, "click", () => next(-1)); - on(following, "click", () => next()); - search(); - return { - next, - get source() { - return source; - }, - set source(text) { - source = String(text); - search(); - }, - get query() { - return input.value; - }, - set query(value) { - input.value = String(value); - search(); - }, - get matchCount() { - return matches.length; - } - }; -} -function developerView(root, { on }) { - on(root, "click", (event) => { - const action = event.target.closest("button,[data-action]"); - if (action && enabled(action)) root.emit("action", { action: action.dataset.action ?? action.textContent.trim() }); - }); - return { setText(text) { - let pre = root.querySelector("pre"); - if (!pre) { - pre = make(root, "pre", { - class: "j3w1-readonly-text", - tabindex: "0", - "aria-label": "Read-only text" - }); - root.firstElementChild.replaceChildren(pre); - } - pre.textContent = String(text); - } }; -} -//#endregion -export { editorSearch as i, chart as n, developerView as r, avatar as t }; diff --git a/packages/ui/dist/copy/diff-view/runtime/chunks/display-l54fb8vw.js b/packages/ui/dist/copy/diff-view/runtime/chunks/display-l54fb8vw.js new file mode 100644 index 000000000..b2f57aaf2 --- /dev/null +++ b/packages/ui/dist/copy/diff-view/runtime/chunks/display-l54fb8vw.js @@ -0,0 +1,211 @@ +import { i as all, l as make, o as enabled } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/display.js +function avatar(root, { on }) { + const frame = root.querySelector(".avatar"), fallback = root.querySelector("[data-avatar-fallback]"); + if (!frame || !fallback) return {}; + let image = frame.querySelector("img"); + if (!image) { + image = make(root, "img", { + alt: "", + hidden: "" + }); + frame.prepend(image); + } + let source = image.getAttribute("src") ?? ""; + const update = (value) => { + source = String(value ?? ""); + image.hidden = true; + fallback.hidden = false; + delete frame.dataset.error; + if (!source) { + image.removeAttribute("src"); + delete frame.dataset.loading; + return; + } + frame.dataset.loading = "true"; + image.src = source; + }; + on(image, "load", () => { + delete frame.dataset.loading; + image.hidden = false; + fallback.hidden = true; + }); + on(image, "error", () => { + delete frame.dataset.loading; + frame.dataset.error = "true"; + image.hidden = true; + fallback.hidden = false; + }); + update(root.getAttribute("src") ?? source); + return { + get src() { + return source; + }, + set src(value) { + update(value); + }, + attributeChanged(name) { + if (name === "src") update(root.getAttribute("src")); + } + }; +} +function chart(root) { + const figure = root.querySelector("figure"), svg = figure?.querySelector("svg"), tbody = figure?.querySelector("tbody"); + if (!figure || !svg || !tbody) return {}; + let values = all(tbody, "tr").map((row) => ({ + label: row.cells[0]?.textContent.trim() ?? "", + value: Number(row.cells[1]?.textContent) + })); + const update = (data) => { + if (!Array.isArray(data) || data.length > 200 || data.some((row) => typeof row.label !== "string" || typeof row.value !== "number" || !Number.isFinite(row.value) || row.value < 0)) throw new TypeError("data must contain at most 200 labelled finite non-negative values"); + values = data.map((row) => ({ + label: row.label, + value: row.value + })); + svg.replaceChildren(); + tbody.replaceChildren(); + const ns = "http://www.w3.org/2000/svg"; + const group = root.ownerDocument.createElementNS(ns, "g"); + group.setAttribute("class", "chart-series"); + svg.append(group); + const width = Math.max(300, values.length * 32), max = Math.max(1, ...values.map((row) => row.value)); + svg.setAttribute("viewBox", `0 0 ${width} 140`); + svg.setAttribute("aria-label", values.length ? values.map((row) => `${row.label}: ${row.value}`).join("; ") : "No data available"); + for (const [index, row] of values.entries()) { + const bar = root.ownerDocument.createElementNS(ns, "rect"), step = (width - 20) / values.length, height = row.value / max * 100; + for (const [name, value] of Object.entries({ + x: 10 + index * step + step * .15, + y: 110 - height, + width: step * .7, + height + })) bar.setAttribute(name, String(value)); + const title = root.ownerDocument.createElementNS(ns, "title"); + title.textContent = `${row.label}: ${row.value}`; + bar.append(title); + group.append(bar); + const tr = make(root, "tr"); + tr.append(make(root, "th", { scope: "row" }, row.label), make(root, "td", {}, row.value)); + tbody.append(tr); + } + svg.toggleAttribute("hidden", !values.length); + const empty = figure.querySelector("[data-chart-empty]"); + if (empty) empty.hidden = values.length !== 0; + }; + return { + get data() { + return values.map((row) => ({ ...row })); + }, + set data(data) { + update(data); + } + }; +} +function editorSearch(root, { on }) { + const input = root.querySelector("[data-query]"), pre = root.querySelector("[data-source]"), status = root.querySelector("[data-search-status]"); + if (!input || !pre) return {}; + let source = pre.textContent, current = -1, matches = []; + const previous = root.querySelector("[data-previous]"), following = root.querySelector("[data-next]"); + const select = (index) => { + current = matches.length ? (index + matches.length) % matches.length : -1; + all(pre, "mark").forEach((mark, i) => mark.toggleAttribute("data-current", i === current)); + if (status) status.textContent = !input.value ? "Enter text to search." : matches.length ? `Match ${current + 1} of ${matches.length}` : "No matches."; + }; + const search = () => { + matches = []; + pre.replaceChildren(); + const query = input.value.toLocaleLowerCase(); + let folded = "", offset = 0; + const starts = [], ends = []; + for (const char of source) { + const text = char.toLocaleLowerCase(); + for (let i = 0; i < text.length; i++) { + starts.push(offset); + ends.push(offset + char.length); + } + folded += text; + offset += char.length; + } + if (query) { + let position = 0; + while ((position = folded.indexOf(query, position)) >= 0) { + const start = starts[position], end = ends[position + query.length - 1]; + if (!matches.length || start >= matches.at(-1).end) matches.push({ + start, + end + }); + position += query.length; + } + } + let cursor = 0; + for (const match of matches) { + pre.append(root.ownerDocument.createTextNode(source.slice(cursor, match.start)), make(root, "mark", {}, source.slice(match.start, match.end))); + cursor = match.end; + } + pre.append(root.ownerDocument.createTextNode(source.slice(cursor))); + if (previous) previous.disabled = !matches.length; + if (following) following.disabled = !matches.length; + select(0); + }; + const next = (direction = 1) => { + if (!matches.length) return; + select(current + (direction < 0 ? -1 : 1)); + all(pre, "mark")[current]?.scrollIntoView({ + block: "nearest", + inline: "nearest" + }); + }; + on(input, "input", search); + on(input, "keydown", (event) => { + if (event.key === "Enter") { + event.preventDefault(); + next(event.shiftKey ? -1 : 1); + } else if (event.key === "Escape" && input.value) { + event.preventDefault(); + event.stopPropagation(); + input.value = ""; + search(); + } + }); + on(previous, "click", () => next(-1)); + on(following, "click", () => next()); + search(); + return { + next, + get source() { + return source; + }, + set source(text) { + source = String(text); + search(); + }, + get query() { + return input.value; + }, + set query(value) { + input.value = String(value); + search(); + }, + get matchCount() { + return matches.length; + } + }; +} +function developerView(root, { on }) { + on(root, "click", (event) => { + const action = event.target.closest("button,[data-action]"); + if (action && enabled(action)) root.emit("action", { action: action.dataset.action ?? action.textContent.trim() }); + }); + return { setText(text) { + let pre = root.querySelector("pre"); + if (!pre) { + pre = make(root, "pre", { + class: "j3w1-readonly-text", + tabindex: "0", + "aria-label": "Read-only text" + }); + root.firstElementChild.replaceChildren(pre); + } + pre.textContent = String(text); + } }; +} +export { editorSearch as i, chart as n, developerView as r, avatar as t }; diff --git a/packages/ui/dist/copy/diff-view/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/diff-view/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/diff-view/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/diff-view/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/diff-view/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/diff-view/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/diff-view/runtime/components/diff-view.js b/packages/ui/dist/copy/diff-view/runtime/components/diff-view.js index 47f8bf1a3..3daf06ec6 100644 --- a/packages/ui/dist/copy/diff-view/runtime/components/diff-view.js +++ b/packages/ui/dist/copy/diff-view/runtime/components/diff-view.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as developerView } from "../chunks/display-Jm9bAsnb.js"; -//#region .cache/ui-build/entries/components/diff-view.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as developerView } from "../chunks/display-l54fb8vw.js"; +// .cache/ui-build/entries/components/diff-view.js var J3w1DiffView = class extends J3w1Element { static componentId = "diff-view"; static version = "4.0.0"; - static implementationId = "sha256-7zzFpU0Y2cQR1wO8DWE4bqkofCnJMaERCXRLdai7u0A="; + static implementationId = "sha256-xbLfnA1/siCeNpzpHk8FA2PFnz+aDd3RON68QHJ7WnM="; static connect = developerView; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -13,5 +13,4 @@ var J3w1DiffView = class extends J3w1Element { return this._api.setText(...args); } }; -//#endregion export { J3w1DiffView }; diff --git a/packages/ui/dist/copy/diff-view/runtime/register/diff-view.js b/packages/ui/dist/copy/diff-view/runtime/register/diff-view.js index 92fc87c5c..3de702302 100644 --- a/packages/ui/dist/copy/diff-view/runtime/register/diff-view.js +++ b/packages/ui/dist/copy/diff-view/runtime/register/diff-view.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1DiffView } from "../components/diff-view.js"; -//#region .cache/ui-build/entries/register/diff-view.js +// .cache/ui-build/entries/register/diff-view.js var element = registerElement("j3w1-diff-view", J3w1DiffView); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/disclosure/manifest.json b/packages/ui/dist/copy/disclosure/manifest.json index 289962207..9ead2b351 100644 --- a/packages/ui/dist/copy/disclosure/manifest.json +++ b/packages/ui/dist/copy/disclosure/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/disclosure.md", "dependencies": [ "register/disclosure.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/disclosure.js", - "chunks/navigation-BfNzDYZB.js" + "chunks/navigation-CknoksQ5.js" ], "files": { - "runtime/register/disclosure.js": "sha256-aIVSvVhr919KN1yvujNgB9MkM76nINbjI5fn2aI15hU=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/disclosure.js": "sha256-+8hk74Zg9ZUq3AstqnrP14hMWYJ2J3MQ8RCtpk4njOs=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", + "runtime/register/disclosure.js": "sha256-riSMKtiydJYp+gWIuJjvZQ0pyMKP1gGwilg6ENPUQyw=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/disclosure.js": "sha256-+iFBNYQitu+xCVINfUUYfDi8EX1/Lpn2cpZEvFr44os=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-M/UOvBwScEgDLtRZmuBaxCwOBb1g0hkfyHqaxsEDfHk=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/disclosure/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/disclosure/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/disclosure/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/disclosure/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/disclosure/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/disclosure/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/disclosure/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/disclosure/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/disclosure/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/disclosure/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/disclosure/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/disclosure/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/disclosure/runtime/chunks/navigation-BfNzDYZB.js b/packages/ui/dist/copy/disclosure/runtime/chunks/navigation-BfNzDYZB.js deleted file mode 100644 index db2779553..000000000 --- a/packages/ui/dist/copy/disclosure/runtime/chunks/navigation-BfNzDYZB.js +++ /dev/null @@ -1,377 +0,0 @@ -import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/navigation.js -function tabs(root, { on }, listOverride) { - const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); - if (!list) return {}; - const items = () => all(list, "[role=\"tab\"]").filter(enabled); - const select = (id, focus = false) => { - const tab = items().find((item) => item.id === id); - if (!tab) throw new RangeError(`Unknown enabled tab: ${id}`); - all(list, "[role=\"tab\"]").forEach((item) => { - item.setAttribute("aria-selected", String(item === tab)); - item.tabIndex = item === tab ? 0 : -1; - }); - all(root, "[role=\"tabpanel\"]").filter((panel) => all(list, "[role=\"tab\"]").some((tab) => tab.getAttribute("aria-controls") === panel.id)).forEach((panel) => { - panel.hidden = panel.id !== tab.getAttribute("aria-controls"); - if (!panel.hidden && !panel.querySelector("a[href],button,input,select,textarea,[tabindex='0']")) panel.tabIndex = 0; - }); - if (focus) tab.focus(); - return tab; - }; - const activate = (tab) => { - select(tab.id); - root.emit("select", { - id: tab.id, - panelId: tab.getAttribute("aria-controls") - }); - }; - on(list, "click", (event) => { - const tab = event.target.closest("[role=\"tab\"]"); - if (tab && enabled(tab)) activate(tab); - }); - on(list, "keydown", (event) => { - const current = event.target.closest("[role=\"tab\"]"), options = items(); - if (!current) return; - const vertical = list.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(list).direction === "rtl"; - const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", previous = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; - let index = options.indexOf(current); - if (event.key === next) index++; - else if (event.key === previous) index--; - else if (event.key === "Home") index = 0; - else if (event.key === "End") index = options.length - 1; - else if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - activate(current); - return; - } else return; - event.preventDefault(); - const tab = rove(options, index); - if (root.getAttribute("activation") !== "manual") activate(tab); - }); - const initial = items().find((item) => item.getAttribute("aria-selected") === "true") ?? items()[0]; - if (initial) select(initial.id); - return { - select, - get selectedId() { - return list.querySelector("[aria-selected=\"true\"]")?.id ?? ""; - }, - set selectedId(id) { - select(id); - } - }; -} -function toolbar(root, { on }) { - const bar = root.querySelector("[role=\"toolbar\"]"); - if (!bar) return {}; - const controls = () => all(bar, "button,a[href],input,select").filter((node) => enabled(node) && visible(node) && !node.closest("[role=\"menu\"]")); - const initial = controls(); - rove(initial, Math.max(0, initial.findIndex((node) => node.tabIndex === 0)), false); - on(bar, "focusin", (event) => { - if (controls().includes(event.target)) rove(controls(), controls().indexOf(event.target), false); - }); - on(bar, "keydown", (event) => { - if (event.target.matches("input,select,textarea") || event.target.closest("[role=\"menu\"]")) return; - const items = controls(), index = items.indexOf(event.target); - const vertical = bar.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(bar).direction === "rtl"; - const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", prev = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; - if (![ - next, - prev, - "Home", - "End" - ].includes(event.key)) return; - event.preventDefault(); - rove(items, keyIndex({ - key: event.key, - index, - length: items.length, - next, - previous: prev - })); - }); - on(bar, "click", (event) => { - const button = event.target.closest("button[aria-pressed]"); - if (button && enabled(button)) { - button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - root.emit("action", { - action: button.dataset.action ?? button.textContent.trim(), - pressed: button.getAttribute("aria-pressed") === "true" - }); - } - }); - return {}; -} -function disclosure(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button[aria-controls][aria-expanded]"); - if (!button || !enabled(button)) return; - const target = root.querySelector(`#${CSS.escape(button.getAttribute("aria-controls"))}`); - if (!target) return; - const expanded = button.getAttribute("aria-expanded") !== "true"; - button.setAttribute("aria-expanded", String(expanded)); - target.hidden = !expanded; - root.emit("toggle", { - id: target.id, - expanded - }); - }); - const details = root.querySelector("details"); - on(details, "toggle", () => root.emit("toggle", { - id: details.id, - expanded: details.open - })); - return { - get open() { - return details?.open ?? false; - }, - set open(value) { - if (details) details.open = Boolean(value); - } - }; -} -function combobox(root, { on, signal }) { - const input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"); - if (!input || !list) return {}; - identify(root, list, "options"); - input.setAttribute("aria-controls", list.id); - let active = null, notifying = false; - const notify = () => { - notifying = true; - try { - nativeInput(input); - nativeInput(input, "change"); - } finally { - notifying = false; - } - }; - const options = () => all(list, "[role=\"option\"]").filter((node) => enabled(node) && !node.hidden && !node.closest("[role=\"group\"][hidden]")); - all(list, "[role=\"option\"]").forEach((option, index) => identify(root, option, `option-${index}`)); - const setActive = (option) => { - active = option; - all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); - if (option) { - input.setAttribute("aria-activedescendant", option.id); - option.scrollIntoView({ block: "nearest" }); - } else input.removeAttribute("aria-activedescendant"); - }; - const hide = () => { - list.hidden = true; - input.setAttribute("aria-expanded", "false"); - setActive(null); - }; - const filter = (query = input.value) => { - for (const option of all(list, "[role=\"option\"]")) if (enabled(option)) option.hidden = !option.textContent.toLocaleLowerCase().includes(query.toLocaleLowerCase()); - all(list, "[role=\"group\"]").forEach((group) => { - group.hidden = !all(group, "[role=\"option\"]").some((node) => enabled(node) && !node.hidden); - }); - const empty = root.querySelector(".combobox-empty"); - if (empty) { - empty.hidden = options().length !== 0; - empty.classList.toggle("combobox-empty-shown", !empty.hidden); - } - if (!options().includes(active)) setActive(null); - }; - const show = (allOptions = false) => { - if (!enabled(input) || input.readOnly) return; - filter(allOptions ? "" : input.value); - list.hidden = false; - input.setAttribute("aria-expanded", "true"); - place(input, list); - }; - const choose = (option) => { - if (!option || !enabled(option)) return; - input.value = option.dataset.value ?? option.textContent.trim(); - hide(); - notify(); - input.focus(); - }; - on(input, "input", () => { - if (!notifying) { - show(); - announce(root, `${options().length} options available.`); - } - }); - on(input, "keydown", (event) => { - if (event.key === "Tab") { - hide(); - return; - } - if (event.key === "Escape") { - if (!list.hidden) { - hide(); - event.stopPropagation(); - } else if (input.value) { - input.value = ""; - notify(); - event.stopPropagation(); - } - event.preventDefault(); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - hide(); - return; - } - if (["ArrowDown", "ArrowUp"].includes(event.key)) { - event.preventDefault(); - if (list.hidden) show(true); - if (event.altKey) return; - const items = options(), index = active ? items.indexOf(active) : event.key === "ArrowDown" ? -1 : 0; - if (items.length) setActive(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); - } else if (event.key === "Enter" && !list.hidden && active) { - event.preventDefault(); - choose(active); - } - }); - on(list, "pointerdown", (event) => { - if (event.target.closest("[role=\"option\"]")) event.preventDefault(); - }); - on(list, "click", (event) => choose(event.target.closest("[role=\"option\"]"))); - on(root.querySelector(".combobox-toggle"), "click", () => { - list.hidden ? show(true) : hide(); - input.focus(); - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!root.contains(event.target)) hide(); - }); - on(root, "focusout", () => queueMicrotask(() => { - if (!signal.aborted && !root.contains(root.ownerDocument.activeElement)) hide(); - })); - on(root.ownerDocument.defaultView, "resize", () => { - if (!list.hidden) place(input, list); - }); - on(root.ownerDocument, "scroll", (event) => { - if (!list.hidden && !list.contains(event.target)) place(input, list); - }, { capture: true }); - hide(); - return { - show, - hide, - get open() { - return !list.hidden; - }, - set open(value) { - value ? show() : hide(); - }, - get value() { - return input.value; - }, - set value(value) { - input.value = String(value ?? ""); - if (!list.hidden) filter(); - }, - cleanup: hide - }; -} -function menu(root, { on }) { - const trigger = root.querySelector("button[aria-haspopup=\"menu\"]"), main = root.querySelector("[role=\"menu\"]"); - if (!trigger || !main) return {}; - identify(root, main, "menu"); - trigger.setAttribute("aria-controls", main.id); - const lists = all(root, "[role=\"menu\"]"); - const items = (list) => all(list, "[role^=\"menuitem\"]").filter((item) => item.closest("[role=\"menu\"]") === list); - const controller = (list) => all(root, "[aria-controls]").find((node) => node.getAttribute("aria-controls") === list.id); - const closeList = (list) => { - list.hidden = true; - controller(list)?.setAttribute("aria-expanded", "false"); - }; - const hide = (focus = true) => { - lists.forEach(closeList); - if (focus) trigger.focus(); - }; - const showList = (list, button, last = false) => { - list.hidden = false; - button.setAttribute("aria-expanded", "true"); - place(button, list); - rove(items(list), last ? items(list).length - 1 : 0); - }; - const show = () => { - if (enabled(trigger)) showList(main, trigger); - }; - const submenu = (button) => button.hasAttribute("aria-haspopup") ? lists.find((list) => list.id === button.getAttribute("aria-controls")) : null; - const activate = (item) => { - if (!enabled(item)) return; - const child = submenu(item); - if (child) { - showList(child, item); - return; - } - if (item.getAttribute("role") === "menuitemcheckbox") item.setAttribute("aria-checked", String(item.getAttribute("aria-checked") !== "true")); - else if (item.getAttribute("role") === "menuitemradio") items(item.closest("[role=\"menu\"]")).filter((node) => node.getAttribute("role") === "menuitemradio").forEach((node) => node.setAttribute("aria-checked", String(node === item))); - else hide(); - root.emit("action", { - action: item.dataset.action ?? item.textContent.trim(), - checked: item.getAttribute("aria-checked") === "true" - }); - }; - on(trigger, "click", () => main.hidden ? show() : hide()); - on(trigger, "keydown", (event) => { - if (["ArrowDown", "ArrowUp"].includes(event.key) && enabled(trigger)) { - event.preventDefault(); - showList(main, trigger, event.key === "ArrowUp"); - } - }); - on(root, "click", (event) => { - const item = event.target.closest("[role^=\"menuitem\"]"); - if (item) activate(item); - }); - on(root, "keydown", (event) => { - const item = event.target.closest("[role^=\"menuitem\"]"); - if (!item) return; - const list = item.closest("[role=\"menu\"]"), options = items(list), index = options.indexOf(item), rtl = getComputedStyle(list).direction === "rtl"; - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - rove(options, keyIndex({ - key: event.key, - index, - length: options.length - })); - } else if (event.key === "Escape" || event.key === (rtl ? "ArrowRight" : "ArrowLeft") && list !== main) { - event.preventDefault(); - event.stopPropagation(); - if (list !== main) { - closeList(list); - controller(list)?.focus(); - } else hide(); - } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight") && submenu(item)) { - event.preventDefault(); - showList(submenu(item), item); - } else if (event.key === "Tab") hide(); - else if (event.key.length === 1 && /\S/.test(event.key)) { - const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(".menu-label") ?? node).textContent.trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); - if (found) { - event.preventDefault(); - rove(options, options.indexOf(found)); - } - } - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!root.contains(event.target)) hide(false); - }); - on(root.ownerDocument, "focusin", (event) => { - if (!root.contains(event.target)) hide(false); - }); - on(root.ownerDocument.defaultView, "resize", () => lists.filter((list) => !list.hidden).forEach((list) => place(controller(list), list))); - hide(false); - return { - show, - hide, - get open() { - return !main.hidden; - }, - set open(value) { - value ? show() : hide(false); - }, - cleanup() { - hide(false); - } - }; -} -//#endregion -export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/disclosure/runtime/chunks/navigation-CknoksQ5.js b/packages/ui/dist/copy/disclosure/runtime/chunks/navigation-CknoksQ5.js new file mode 100644 index 000000000..dfd1883e6 --- /dev/null +++ b/packages/ui/dist/copy/disclosure/runtime/chunks/navigation-CknoksQ5.js @@ -0,0 +1,376 @@ +import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/navigation.js +function tabs(root, { on }, listOverride) { + const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); + if (!list) return {}; + const items = () => all(list, "[role=\"tab\"]").filter(enabled); + const select = (id, focus = false) => { + const tab = items().find((item) => item.id === id); + if (!tab) throw new RangeError(`Unknown enabled tab: ${id}`); + all(list, "[role=\"tab\"]").forEach((item) => { + item.setAttribute("aria-selected", String(item === tab)); + item.tabIndex = item === tab ? 0 : -1; + }); + all(root, "[role=\"tabpanel\"]").filter((panel) => all(list, "[role=\"tab\"]").some((tab) => tab.getAttribute("aria-controls") === panel.id)).forEach((panel) => { + panel.hidden = panel.id !== tab.getAttribute("aria-controls"); + if (!panel.hidden && !panel.querySelector("a[href],button,input,select,textarea,[tabindex='0']")) panel.tabIndex = 0; + }); + if (focus) tab.focus(); + return tab; + }; + const activate = (tab) => { + select(tab.id); + root.emit("select", { + id: tab.id, + panelId: tab.getAttribute("aria-controls") + }); + }; + on(list, "click", (event) => { + const tab = event.target.closest("[role=\"tab\"]"); + if (tab && enabled(tab)) activate(tab); + }); + on(list, "keydown", (event) => { + const current = event.target.closest("[role=\"tab\"]"), options = items(); + if (!current) return; + const vertical = list.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(list).direction === "rtl"; + const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", previous = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; + let index = options.indexOf(current); + if (event.key === next) index++; + else if (event.key === previous) index--; + else if (event.key === "Home") index = 0; + else if (event.key === "End") index = options.length - 1; + else if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + activate(current); + return; + } else return; + event.preventDefault(); + const tab = rove(options, index); + if (root.getAttribute("activation") !== "manual") activate(tab); + }); + const initial = items().find((item) => item.getAttribute("aria-selected") === "true") ?? items()[0]; + if (initial) select(initial.id); + return { + select, + get selectedId() { + return list.querySelector("[aria-selected=\"true\"]")?.id ?? ""; + }, + set selectedId(id) { + select(id); + } + }; +} +function toolbar(root, { on }) { + const bar = root.querySelector("[role=\"toolbar\"]"); + if (!bar) return {}; + const controls = () => all(bar, "button,a[href],input,select").filter((node) => enabled(node) && visible(node) && !node.closest("[role=\"menu\"]")); + const initial = controls(); + rove(initial, Math.max(0, initial.findIndex((node) => node.tabIndex === 0)), false); + on(bar, "focusin", (event) => { + if (controls().includes(event.target)) rove(controls(), controls().indexOf(event.target), false); + }); + on(bar, "keydown", (event) => { + if (event.target.matches("input,select,textarea") || event.target.closest("[role=\"menu\"]")) return; + const items = controls(), index = items.indexOf(event.target); + const vertical = bar.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(bar).direction === "rtl"; + const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", prev = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; + if (![ + next, + prev, + "Home", + "End" + ].includes(event.key)) return; + event.preventDefault(); + rove(items, keyIndex({ + key: event.key, + index, + length: items.length, + next, + previous: prev + })); + }); + on(bar, "click", (event) => { + const button = event.target.closest("button[aria-pressed]"); + if (button && enabled(button)) { + button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + root.emit("action", { + action: button.dataset.action ?? button.textContent.trim(), + pressed: button.getAttribute("aria-pressed") === "true" + }); + } + }); + return {}; +} +function disclosure(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button[aria-controls][aria-expanded]"); + if (!button || !enabled(button)) return; + const target = root.querySelector(`#${CSS.escape(button.getAttribute("aria-controls"))}`); + if (!target) return; + const expanded = button.getAttribute("aria-expanded") !== "true"; + button.setAttribute("aria-expanded", String(expanded)); + target.hidden = !expanded; + root.emit("toggle", { + id: target.id, + expanded + }); + }); + const details = root.querySelector("details"); + on(details, "toggle", () => root.emit("toggle", { + id: details.id, + expanded: details.open + })); + return { + get open() { + return details?.open ?? false; + }, + set open(value) { + if (details) details.open = Boolean(value); + } + }; +} +function combobox(root, { on, signal }) { + const input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"); + if (!input || !list) return {}; + identify(root, list, "options"); + input.setAttribute("aria-controls", list.id); + let active = null, notifying = false; + const notify = () => { + notifying = true; + try { + nativeInput(input); + nativeInput(input, "change"); + } finally { + notifying = false; + } + }; + const options = () => all(list, "[role=\"option\"]").filter((node) => enabled(node) && !node.hidden && !node.closest("[role=\"group\"][hidden]")); + all(list, "[role=\"option\"]").forEach((option, index) => identify(root, option, `option-${index}`)); + const setActive = (option) => { + active = option; + all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); + if (option) { + input.setAttribute("aria-activedescendant", option.id); + option.scrollIntoView({ block: "nearest" }); + } else input.removeAttribute("aria-activedescendant"); + }; + const hide = () => { + list.hidden = true; + input.setAttribute("aria-expanded", "false"); + setActive(null); + }; + const filter = (query = input.value) => { + for (const option of all(list, "[role=\"option\"]")) if (enabled(option)) option.hidden = !option.textContent.toLocaleLowerCase().includes(query.toLocaleLowerCase()); + all(list, "[role=\"group\"]").forEach((group) => { + group.hidden = !all(group, "[role=\"option\"]").some((node) => enabled(node) && !node.hidden); + }); + const empty = root.querySelector(".combobox-empty"); + if (empty) { + empty.hidden = options().length !== 0; + empty.classList.toggle("combobox-empty-shown", !empty.hidden); + } + if (!options().includes(active)) setActive(null); + }; + const show = (allOptions = false) => { + if (!enabled(input) || input.readOnly) return; + filter(allOptions ? "" : input.value); + list.hidden = false; + input.setAttribute("aria-expanded", "true"); + place(input, list); + }; + const choose = (option) => { + if (!option || !enabled(option)) return; + input.value = option.dataset.value ?? option.textContent.trim(); + hide(); + notify(); + input.focus(); + }; + on(input, "input", () => { + if (!notifying) { + show(); + announce(root, `${options().length} options available.`); + } + }); + on(input, "keydown", (event) => { + if (event.key === "Tab") { + hide(); + return; + } + if (event.key === "Escape") { + if (!list.hidden) { + hide(); + event.stopPropagation(); + } else if (input.value) { + input.value = ""; + notify(); + event.stopPropagation(); + } + event.preventDefault(); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + hide(); + return; + } + if (["ArrowDown", "ArrowUp"].includes(event.key)) { + event.preventDefault(); + if (list.hidden) show(true); + if (event.altKey) return; + const items = options(), index = active ? items.indexOf(active) : event.key === "ArrowDown" ? -1 : 0; + if (items.length) setActive(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); + } else if (event.key === "Enter" && !list.hidden && active) { + event.preventDefault(); + choose(active); + } + }); + on(list, "pointerdown", (event) => { + if (event.target.closest("[role=\"option\"]")) event.preventDefault(); + }); + on(list, "click", (event) => choose(event.target.closest("[role=\"option\"]"))); + on(root.querySelector(".combobox-toggle"), "click", () => { + list.hidden ? show(true) : hide(); + input.focus(); + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!root.contains(event.target)) hide(); + }); + on(root, "focusout", () => queueMicrotask(() => { + if (!signal.aborted && !root.contains(root.ownerDocument.activeElement)) hide(); + })); + on(root.ownerDocument.defaultView, "resize", () => { + if (!list.hidden) place(input, list); + }); + on(root.ownerDocument, "scroll", (event) => { + if (!list.hidden && !list.contains(event.target)) place(input, list); + }, { capture: true }); + hide(); + return { + show, + hide, + get open() { + return !list.hidden; + }, + set open(value) { + value ? show() : hide(); + }, + get value() { + return input.value; + }, + set value(value) { + input.value = String(value ?? ""); + if (!list.hidden) filter(); + }, + cleanup: hide + }; +} +function menu(root, { on }) { + const trigger = root.querySelector("button[aria-haspopup=\"menu\"]"), main = root.querySelector("[role=\"menu\"]"); + if (!trigger || !main) return {}; + identify(root, main, "menu"); + trigger.setAttribute("aria-controls", main.id); + const lists = all(root, "[role=\"menu\"]"); + const items = (list) => all(list, "[role^=\"menuitem\"]").filter((item) => item.closest("[role=\"menu\"]") === list); + const controller = (list) => all(root, "[aria-controls]").find((node) => node.getAttribute("aria-controls") === list.id); + const closeList = (list) => { + list.hidden = true; + controller(list)?.setAttribute("aria-expanded", "false"); + }; + const hide = (focus = true) => { + lists.forEach(closeList); + if (focus) trigger.focus(); + }; + const showList = (list, button, last = false) => { + list.hidden = false; + button.setAttribute("aria-expanded", "true"); + place(button, list); + rove(items(list), last ? items(list).length - 1 : 0); + }; + const show = () => { + if (enabled(trigger)) showList(main, trigger); + }; + const submenu = (button) => button.hasAttribute("aria-haspopup") ? lists.find((list) => list.id === button.getAttribute("aria-controls")) : null; + const activate = (item) => { + if (!enabled(item)) return; + const child = submenu(item); + if (child) { + showList(child, item); + return; + } + if (item.getAttribute("role") === "menuitemcheckbox") item.setAttribute("aria-checked", String(item.getAttribute("aria-checked") !== "true")); + else if (item.getAttribute("role") === "menuitemradio") items(item.closest("[role=\"menu\"]")).filter((node) => node.getAttribute("role") === "menuitemradio").forEach((node) => node.setAttribute("aria-checked", String(node === item))); + else hide(); + root.emit("action", { + action: item.dataset.action ?? item.textContent.trim(), + checked: item.getAttribute("aria-checked") === "true" + }); + }; + on(trigger, "click", () => main.hidden ? show() : hide()); + on(trigger, "keydown", (event) => { + if (["ArrowDown", "ArrowUp"].includes(event.key) && enabled(trigger)) { + event.preventDefault(); + showList(main, trigger, event.key === "ArrowUp"); + } + }); + on(root, "click", (event) => { + const item = event.target.closest("[role^=\"menuitem\"]"); + if (item) activate(item); + }); + on(root, "keydown", (event) => { + const item = event.target.closest("[role^=\"menuitem\"]"); + if (!item) return; + const list = item.closest("[role=\"menu\"]"), options = items(list), index = options.indexOf(item), rtl = getComputedStyle(list).direction === "rtl"; + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + rove(options, keyIndex({ + key: event.key, + index, + length: options.length + })); + } else if (event.key === "Escape" || event.key === (rtl ? "ArrowRight" : "ArrowLeft") && list !== main) { + event.preventDefault(); + event.stopPropagation(); + if (list !== main) { + closeList(list); + controller(list)?.focus(); + } else hide(); + } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight") && submenu(item)) { + event.preventDefault(); + showList(submenu(item), item); + } else if (event.key === "Tab") hide(); + else if (event.key.length === 1 && /\S/.test(event.key)) { + const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(".menu-label") ?? node).textContent.trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); + if (found) { + event.preventDefault(); + rove(options, options.indexOf(found)); + } + } + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!root.contains(event.target)) hide(false); + }); + on(root.ownerDocument, "focusin", (event) => { + if (!root.contains(event.target)) hide(false); + }); + on(root.ownerDocument.defaultView, "resize", () => lists.filter((list) => !list.hidden).forEach((list) => place(controller(list), list))); + hide(false); + return { + show, + hide, + get open() { + return !main.hidden; + }, + set open(value) { + value ? show() : hide(false); + }, + cleanup() { + hide(false); + } + }; +} +export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/disclosure/runtime/components/disclosure.js b/packages/ui/dist/copy/disclosure/runtime/components/disclosure.js index 56e4f17fd..6b8aeeb30 100644 --- a/packages/ui/dist/copy/disclosure/runtime/components/disclosure.js +++ b/packages/ui/dist/copy/disclosure/runtime/components/disclosure.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as disclosure } from "../chunks/navigation-BfNzDYZB.js"; -//#region .cache/ui-build/entries/components/disclosure.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as disclosure } from "../chunks/navigation-CknoksQ5.js"; +// .cache/ui-build/entries/components/disclosure.js var J3w1Disclosure = class extends J3w1Element { static componentId = "disclosure"; static version = "4.0.0"; - static implementationId = "sha256-h35ty1HDvIv+l1TZ2KWtUtdJetenP1x1+OVPFVOsByg="; + static implementationId = "sha256-/iZ0e5fT3U5WA2/XRKI9hazrMgnbC8vuSxv50Cf3A2g="; static connect = disclosure; static upgradeProperties = [ "disabled", @@ -24,5 +24,4 @@ var J3w1Disclosure = class extends J3w1Element { }); } }; -//#endregion export { J3w1Disclosure }; diff --git a/packages/ui/dist/copy/disclosure/runtime/register/disclosure.js b/packages/ui/dist/copy/disclosure/runtime/register/disclosure.js index 76f4c204b..2734916ec 100644 --- a/packages/ui/dist/copy/disclosure/runtime/register/disclosure.js +++ b/packages/ui/dist/copy/disclosure/runtime/register/disclosure.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Disclosure } from "../components/disclosure.js"; -//#region .cache/ui-build/entries/register/disclosure.js +// .cache/ui-build/entries/register/disclosure.js var element = registerElement("j3w1-disclosure", J3w1Disclosure); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/drawer/manifest.json b/packages/ui/dist/copy/drawer/manifest.json index cbbb78318..8f617e0d1 100644 --- a/packages/ui/dist/copy/drawer/manifest.json +++ b/packages/ui/dist/copy/drawer/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/drawer.md", "dependencies": [ "register/drawer.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/drawer.js", - "chunks/overlays-BwgpF4jI.js" + "chunks/overlays-BW66WXLm.js" ], "files": { - "runtime/register/drawer.js": "sha256-rA72wn/EhgwDqOffVBPLtBX9zTwVRgod2uadIlZcLe0=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/drawer.js": "sha256-1YuAUa33ScDJX74NBdYbrkllPWZ0abGZL2M1hnFJ7A8=", - "runtime/chunks/overlays-BwgpF4jI.js": "sha256-NAd99OT4kDsFp8IHscKRus2jY6XRsq+GMzplWbJsY4U=", + "runtime/register/drawer.js": "sha256-AM5iGLPnmhN77hlMQqOhJM8ZDYwV/jpxf4bjQDWLHlE=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/drawer.js": "sha256-xhVXm6IXbOoRG69KeKgXfir/YRSlIhTVtiygF1/uLwI=", + "runtime/chunks/overlays-BW66WXLm.js": "sha256-Z9etmUpuDuykKbJkriLMz8iiYnOP9uMUAshKwoHc1I8=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-r9vwT85nLqMxpyVzGQDrQIU3bpOdw5TleRvfLX3IVQs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/drawer/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/drawer/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/drawer/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/drawer/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/drawer/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/drawer/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/drawer/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/drawer/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/drawer/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/drawer/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/drawer/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/drawer/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/drawer/runtime/chunks/overlays-BW66WXLm.js b/packages/ui/dist/copy/drawer/runtime/chunks/overlays-BW66WXLm.js new file mode 100644 index 000000000..d05c73b46 --- /dev/null +++ b/packages/ui/dist/copy/drawer/runtime/chunks/overlays-BW66WXLm.js @@ -0,0 +1,244 @@ +import { d as place, i as all, o as enabled, s as identify } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/overlays.js +function modal(root, { on }) { + const dialog = root.querySelector("dialog"); + if (!dialog) return {}; + let opener = null; + const show = (trigger = root.ownerDocument.activeElement) => { + if (dialog.open || root.hasAttribute("disabled")) return; + opener = trigger; + dialog.showModal(); + (dialog.querySelector("[autofocus]") ?? dialog.querySelector("button:not(.dialog-button-destructive)"))?.focus(); + root.emit("open", {}); + }; + const close = (value = "") => { + if (dialog.open) dialog.close(String(value)); + }; + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (button?.matches("[data-open]")) { + show(button); + return; + } + if (button && dialog.contains(button) && enabled(button)) { + if (button.matches("[data-close],.dialog-close,.drawer-close")) close(button.dataset.close ?? "cancel"); + else if (button.dataset.action && root.emit("action", { action: button.dataset.action })) close(button.dataset.action); + } + if (root.constructor.componentId === "drawer" && event.target.closest("a[href]") && dialog.contains(event.target)) close("navigate"); + }); + on(dialog, "cancel", (event) => { + if (!root.emit("cancel", {})) event.preventDefault(); + }); + on(dialog, "close", () => { + if (opener?.isConnected) opener.focus(); + root.emit("close", { returnValue: dialog.returnValue }); + }); + return { + show, + close, + get open() { + return dialog.open; + }, + set open(value) { + value ? show() : close(); + }, + get returnValue() { + return dialog.returnValue; + }, + cleanup() { + if (dialog.open) dialog.close(); + } + }; +} +function tooltip(root, { on }) { + const trigger = root.querySelector(".tooltip-trigger"), popup = root.querySelector("[role=\"tooltip\"]"); + if (!trigger || !popup) return {}; + identify(root, popup, "tooltip"); + trigger.setAttribute("aria-describedby", popup.id); + let timer, hideTimer, dismissed = false, hovering = false; + const stop = () => { + clearTimeout(timer); + clearTimeout(hideTimer); + }; + const hide = () => { + stop(); + popup.hidden = true; + }; + const show = () => { + stop(); + if (!dismissed) { + popup.hidden = false; + place(trigger, popup); + } + }; + const hideSoon = () => { + clearTimeout(timer); + clearTimeout(hideTimer); + hideTimer = setTimeout(() => { + if (!hovering && root.ownerDocument.activeElement !== trigger) hide(); + }, 300); + }; + on(trigger, "pointerenter", (event) => { + if (event.pointerType !== "touch") { + hovering = true; + dismissed = false; + clearTimeout(hideTimer); + if (popup.hidden) timer = setTimeout(show, 300); + } + }); + on(root, "pointerleave", (event) => { + if (!root.contains(event.relatedTarget)) { + hovering = false; + dismissed = false; + if (root.ownerDocument.activeElement !== trigger) hideSoon(); + } + }); + on(popup, "pointerenter", () => { + hovering = true; + stop(); + }); + on(trigger, "focus", () => { + dismissed = false; + show(); + }); + on(trigger, "blur", () => { + if (!hovering) hide(); + }); + on(trigger, "click", () => { + dismissed = true; + hide(); + }); + on(trigger, "pointerdown", (event) => { + if (event.pointerType === "touch") { + dismissed = false; + timer = setTimeout(show, 500); + } + }); + on(trigger, "pointerup", stop); + on(trigger, "pointercancel", stop); + on(root.ownerDocument, "keydown", (event) => { + if (event.key === "Escape" && !popup.hidden) { + event.preventDefault(); + event.stopImmediatePropagation(); + dismissed = true; + hide(); + } + }, { capture: true }); + on(root.ownerDocument, "scroll", () => { + if (!popup.hidden) place(trigger, popup); + }, { capture: true }); + on(root.ownerDocument.defaultView, "resize", () => { + if (!popup.hidden) place(trigger, popup); + }); + hide(); + return { + show, + hide, + get open() { + return !popup.hidden; + }, + cleanup: hide + }; +} +function popover(root, { on }) { + const trigger = root.querySelector("[data-popover-trigger]"), panel = root.querySelector("[data-popover-panel]"); + if (!trigger || !panel) return {}; + identify(root, panel, "popover"); + trigger.setAttribute("aria-controls", panel.id); + const native = typeof panel.showPopover === "function"; + if (native) { + panel.setAttribute("popover", "auto"); + panel.hidden = false; + } else panel.hidden = true; + let open = false; + const sync = (value) => { + open = value; + trigger.setAttribute("aria-expanded", String(value)); + root.emit("toggle", { expanded: value }); + }; + const show = () => { + if (open || !enabled(trigger)) return; + native ? panel.showPopover() : panel.hidden = false; + sync(true); + place(trigger, panel); + }; + const hide = (focus = false) => { + if (!open) return; + native ? panel.hidePopover() : panel.hidden = true; + sync(false); + if (focus) trigger.focus(); + }; + on(trigger, "click", () => open ? hide() : show()); + on(panel, "beforetoggle", (event) => { + open = event.newState === "open"; + trigger.setAttribute("aria-expanded", String(open)); + }); + on(panel, "click", (event) => { + if (event.target.closest("[data-close]")) hide(true); + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!native && !root.contains(event.target)) hide(); + }); + on(root, "keydown", (event) => { + if (event.key === "Escape" && open) { + event.preventDefault(); + event.stopPropagation(); + hide(true); + } + }); + on(root.ownerDocument.defaultView, "resize", () => { + if (open) place(trigger, panel); + }); + trigger.setAttribute("aria-expanded", "false"); + return { + show, + hide, + get open() { + return open; + }, + set open(value) { + value ? show() : hide(); + }, + cleanup() { + hide(); + } + }; +} +function feedback(root, { on }) { + const dismiss = (item) => { + if (!item || !root.emit("dismiss", { id: item.id })) return; + const hadFocus = item.contains(root.ownerDocument.activeElement); + const focusable = all(root.ownerDocument, "button,a[href],input,select,textarea,[tabindex='0']").filter((node) => enabled(node) && !node.closest("[hidden]")); + const currentIndex = focusable.indexOf(root.ownerDocument.activeElement); + const next = focusable.slice(currentIndex + 1).find((node) => !item.contains(node)) ?? focusable.slice(0, currentIndex).reverse().find((node) => !item.contains(node)); + item.hidden = true; + if (hadFocus) next?.focus(); + }; + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button)) return; + if (button.matches(".toast-close,.alert-close,.chip-remove,[data-dismiss]")) dismiss(button.closest(".toast,.alert,.chip") ?? root); + else if (button.matches(".chip-filter")) { + button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + root.emit("action", { + action: button.textContent.trim(), + pressed: button.getAttribute("aria-pressed") === "true" + }); + } else if (button.matches("[data-retry]")) root.emit("retry", {}); + else root.emit("action", { action: button.dataset.action ?? button.textContent.trim() }); + }); + on(root, "keydown", (event) => { + if (event.key === "Escape") { + const toast = event.target.closest(".toast"); + if (toast) { + event.preventDefault(); + event.stopPropagation(); + dismiss(toast); + } + } + }); + return { dismiss(id) { + dismiss(id ? root.querySelector(`#${CSS.escape(id)}`) : root.querySelector(".toast,.alert") ?? root); + } }; +} +export { tooltip as i, modal as n, popover as r, feedback as t }; diff --git a/packages/ui/dist/copy/drawer/runtime/chunks/overlays-BwgpF4jI.js b/packages/ui/dist/copy/drawer/runtime/chunks/overlays-BwgpF4jI.js deleted file mode 100644 index 4b8de2e8b..000000000 --- a/packages/ui/dist/copy/drawer/runtime/chunks/overlays-BwgpF4jI.js +++ /dev/null @@ -1,245 +0,0 @@ -import { d as place, i as all, o as enabled, s as identify } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/overlays.js -function modal(root, { on }) { - const dialog = root.querySelector("dialog"); - if (!dialog) return {}; - let opener = null; - const show = (trigger = root.ownerDocument.activeElement) => { - if (dialog.open || root.hasAttribute("disabled")) return; - opener = trigger; - dialog.showModal(); - (dialog.querySelector("[autofocus]") ?? dialog.querySelector("button:not(.dialog-button-destructive)"))?.focus(); - root.emit("open", {}); - }; - const close = (value = "") => { - if (dialog.open) dialog.close(String(value)); - }; - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (button?.matches("[data-open]")) { - show(button); - return; - } - if (button && dialog.contains(button) && enabled(button)) { - if (button.matches("[data-close],.dialog-close,.drawer-close")) close(button.dataset.close ?? "cancel"); - else if (button.dataset.action && root.emit("action", { action: button.dataset.action })) close(button.dataset.action); - } - if (root.constructor.componentId === "drawer" && event.target.closest("a[href]") && dialog.contains(event.target)) close("navigate"); - }); - on(dialog, "cancel", (event) => { - if (!root.emit("cancel", {})) event.preventDefault(); - }); - on(dialog, "close", () => { - if (opener?.isConnected) opener.focus(); - root.emit("close", { returnValue: dialog.returnValue }); - }); - return { - show, - close, - get open() { - return dialog.open; - }, - set open(value) { - value ? show() : close(); - }, - get returnValue() { - return dialog.returnValue; - }, - cleanup() { - if (dialog.open) dialog.close(); - } - }; -} -function tooltip(root, { on }) { - const trigger = root.querySelector(".tooltip-trigger"), popup = root.querySelector("[role=\"tooltip\"]"); - if (!trigger || !popup) return {}; - identify(root, popup, "tooltip"); - trigger.setAttribute("aria-describedby", popup.id); - let timer, hideTimer, dismissed = false, hovering = false; - const stop = () => { - clearTimeout(timer); - clearTimeout(hideTimer); - }; - const hide = () => { - stop(); - popup.hidden = true; - }; - const show = () => { - stop(); - if (!dismissed) { - popup.hidden = false; - place(trigger, popup); - } - }; - const hideSoon = () => { - clearTimeout(timer); - clearTimeout(hideTimer); - hideTimer = setTimeout(() => { - if (!hovering && root.ownerDocument.activeElement !== trigger) hide(); - }, 300); - }; - on(trigger, "pointerenter", (event) => { - if (event.pointerType !== "touch") { - hovering = true; - dismissed = false; - clearTimeout(hideTimer); - if (popup.hidden) timer = setTimeout(show, 300); - } - }); - on(root, "pointerleave", (event) => { - if (!root.contains(event.relatedTarget)) { - hovering = false; - dismissed = false; - if (root.ownerDocument.activeElement !== trigger) hideSoon(); - } - }); - on(popup, "pointerenter", () => { - hovering = true; - stop(); - }); - on(trigger, "focus", () => { - dismissed = false; - show(); - }); - on(trigger, "blur", () => { - if (!hovering) hide(); - }); - on(trigger, "click", () => { - dismissed = true; - hide(); - }); - on(trigger, "pointerdown", (event) => { - if (event.pointerType === "touch") { - dismissed = false; - timer = setTimeout(show, 500); - } - }); - on(trigger, "pointerup", stop); - on(trigger, "pointercancel", stop); - on(root.ownerDocument, "keydown", (event) => { - if (event.key === "Escape" && !popup.hidden) { - event.preventDefault(); - event.stopImmediatePropagation(); - dismissed = true; - hide(); - } - }, { capture: true }); - on(root.ownerDocument, "scroll", () => { - if (!popup.hidden) place(trigger, popup); - }, { capture: true }); - on(root.ownerDocument.defaultView, "resize", () => { - if (!popup.hidden) place(trigger, popup); - }); - hide(); - return { - show, - hide, - get open() { - return !popup.hidden; - }, - cleanup: hide - }; -} -function popover(root, { on }) { - const trigger = root.querySelector("[data-popover-trigger]"), panel = root.querySelector("[data-popover-panel]"); - if (!trigger || !panel) return {}; - identify(root, panel, "popover"); - trigger.setAttribute("aria-controls", panel.id); - const native = typeof panel.showPopover === "function"; - if (native) { - panel.setAttribute("popover", "auto"); - panel.hidden = false; - } else panel.hidden = true; - let open = false; - const sync = (value) => { - open = value; - trigger.setAttribute("aria-expanded", String(value)); - root.emit("toggle", { expanded: value }); - }; - const show = () => { - if (open || !enabled(trigger)) return; - native ? panel.showPopover() : panel.hidden = false; - sync(true); - place(trigger, panel); - }; - const hide = (focus = false) => { - if (!open) return; - native ? panel.hidePopover() : panel.hidden = true; - sync(false); - if (focus) trigger.focus(); - }; - on(trigger, "click", () => open ? hide() : show()); - on(panel, "beforetoggle", (event) => { - open = event.newState === "open"; - trigger.setAttribute("aria-expanded", String(open)); - }); - on(panel, "click", (event) => { - if (event.target.closest("[data-close]")) hide(true); - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!native && !root.contains(event.target)) hide(); - }); - on(root, "keydown", (event) => { - if (event.key === "Escape" && open) { - event.preventDefault(); - event.stopPropagation(); - hide(true); - } - }); - on(root.ownerDocument.defaultView, "resize", () => { - if (open) place(trigger, panel); - }); - trigger.setAttribute("aria-expanded", "false"); - return { - show, - hide, - get open() { - return open; - }, - set open(value) { - value ? show() : hide(); - }, - cleanup() { - hide(); - } - }; -} -function feedback(root, { on }) { - const dismiss = (item) => { - if (!item || !root.emit("dismiss", { id: item.id })) return; - const hadFocus = item.contains(root.ownerDocument.activeElement); - const focusable = all(root.ownerDocument, "button,a[href],input,select,textarea,[tabindex='0']").filter((node) => enabled(node) && !node.closest("[hidden]")); - const currentIndex = focusable.indexOf(root.ownerDocument.activeElement); - const next = focusable.slice(currentIndex + 1).find((node) => !item.contains(node)) ?? focusable.slice(0, currentIndex).reverse().find((node) => !item.contains(node)); - item.hidden = true; - if (hadFocus) next?.focus(); - }; - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button)) return; - if (button.matches(".toast-close,.alert-close,.chip-remove,[data-dismiss]")) dismiss(button.closest(".toast,.alert,.chip") ?? root); - else if (button.matches(".chip-filter")) { - button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - root.emit("action", { - action: button.textContent.trim(), - pressed: button.getAttribute("aria-pressed") === "true" - }); - } else if (button.matches("[data-retry]")) root.emit("retry", {}); - else root.emit("action", { action: button.dataset.action ?? button.textContent.trim() }); - }); - on(root, "keydown", (event) => { - if (event.key === "Escape") { - const toast = event.target.closest(".toast"); - if (toast) { - event.preventDefault(); - event.stopPropagation(); - dismiss(toast); - } - } - }); - return { dismiss(id) { - dismiss(id ? root.querySelector(`#${CSS.escape(id)}`) : root.querySelector(".toast,.alert") ?? root); - } }; -} -//#endregion -export { tooltip as i, modal as n, popover as r, feedback as t }; diff --git a/packages/ui/dist/copy/drawer/runtime/components/drawer.js b/packages/ui/dist/copy/drawer/runtime/components/drawer.js index bd2cc2719..e21fa9a5c 100644 --- a/packages/ui/dist/copy/drawer/runtime/components/drawer.js +++ b/packages/ui/dist/copy/drawer/runtime/components/drawer.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as modal } from "../chunks/overlays-BwgpF4jI.js"; -//#region .cache/ui-build/entries/components/drawer.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as modal } from "../chunks/overlays-BW66WXLm.js"; +// .cache/ui-build/entries/components/drawer.js var J3w1Drawer = class extends J3w1Element { static componentId = "drawer"; static version = "4.0.0"; - static implementationId = "sha256-yvpVNrlpyZhfuppx1D3pNtgoOjBrDBDX4gavOIbYSWM="; + static implementationId = "sha256-jlOQ9dUQ9/eHs5sJ9RXnG8JOrwjs9I7YeDZOvcPBU2Q="; static connect = modal; static upgradeProperties = [ "disabled", @@ -35,5 +35,4 @@ var J3w1Drawer = class extends J3w1Element { return this._api?.returnValue; } }; -//#endregion export { J3w1Drawer }; diff --git a/packages/ui/dist/copy/drawer/runtime/register/drawer.js b/packages/ui/dist/copy/drawer/runtime/register/drawer.js index 3ea076673..dcef5181b 100644 --- a/packages/ui/dist/copy/drawer/runtime/register/drawer.js +++ b/packages/ui/dist/copy/drawer/runtime/register/drawer.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Drawer } from "../components/drawer.js"; -//#region .cache/ui-build/entries/register/drawer.js +// .cache/ui-build/entries/register/drawer.js var element = registerElement("j3w1-drawer", J3w1Drawer); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/editor-search/manifest.json b/packages/ui/dist/copy/editor-search/manifest.json index b0ec0a81c..18b4156dd 100644 --- a/packages/ui/dist/copy/editor-search/manifest.json +++ b/packages/ui/dist/copy/editor-search/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/editor-search.md", "dependencies": [ "register/editor-search.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/editor-search.js", - "chunks/display-Jm9bAsnb.js" + "chunks/display-l54fb8vw.js" ], "files": { - "runtime/register/editor-search.js": "sha256-R0CYRlMKJW24RObuaWNYkCNShO/Qtkkh/n9CWJ33FFA=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/editor-search.js": "sha256-aUfiB2u6bRwR1VhsFjANGyo6S0HHuA5lveVDShHVo3c=", - "runtime/chunks/display-Jm9bAsnb.js": "sha256-qZb1g04piEwY3lfFJwMe+0mXR218ljtVi8mepWxrFv8=", + "runtime/register/editor-search.js": "sha256-41yygigjUcGOY69CxJZW+uJFV1ZwXq+Kq/S1Hyh7G8E=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/editor-search.js": "sha256-d2zlER1T0jNTiSDF+a92FN6Tb5wzooCYr1ETcBEY+wc=", + "runtime/chunks/display-l54fb8vw.js": "sha256-xfzo614uMLlSbZc5l+o4vHvrL8yBjQAcV/HJdmPUJ/g=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-EsEJrsGIZ88TEP4pXc0Jt3WQxhCysigIkd1ddeNbHBM=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/editor-search/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/editor-search/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/editor-search/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/editor-search/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/editor-search/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/editor-search/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/editor-search/runtime/chunks/display-Jm9bAsnb.js b/packages/ui/dist/copy/editor-search/runtime/chunks/display-Jm9bAsnb.js deleted file mode 100644 index 5bc817830..000000000 --- a/packages/ui/dist/copy/editor-search/runtime/chunks/display-Jm9bAsnb.js +++ /dev/null @@ -1,212 +0,0 @@ -import { i as all, l as make, o as enabled } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/display.js -function avatar(root, { on }) { - const frame = root.querySelector(".avatar"), fallback = root.querySelector("[data-avatar-fallback]"); - if (!frame || !fallback) return {}; - let image = frame.querySelector("img"); - if (!image) { - image = make(root, "img", { - alt: "", - hidden: "" - }); - frame.prepend(image); - } - let source = image.getAttribute("src") ?? ""; - const update = (value) => { - source = String(value ?? ""); - image.hidden = true; - fallback.hidden = false; - delete frame.dataset.error; - if (!source) { - image.removeAttribute("src"); - delete frame.dataset.loading; - return; - } - frame.dataset.loading = "true"; - image.src = source; - }; - on(image, "load", () => { - delete frame.dataset.loading; - image.hidden = false; - fallback.hidden = true; - }); - on(image, "error", () => { - delete frame.dataset.loading; - frame.dataset.error = "true"; - image.hidden = true; - fallback.hidden = false; - }); - update(root.getAttribute("src") ?? source); - return { - get src() { - return source; - }, - set src(value) { - update(value); - }, - attributeChanged(name) { - if (name === "src") update(root.getAttribute("src")); - } - }; -} -function chart(root) { - const figure = root.querySelector("figure"), svg = figure?.querySelector("svg"), tbody = figure?.querySelector("tbody"); - if (!figure || !svg || !tbody) return {}; - let values = all(tbody, "tr").map((row) => ({ - label: row.cells[0]?.textContent.trim() ?? "", - value: Number(row.cells[1]?.textContent) - })); - const update = (data) => { - if (!Array.isArray(data) || data.length > 200 || data.some((row) => typeof row.label !== "string" || typeof row.value !== "number" || !Number.isFinite(row.value) || row.value < 0)) throw new TypeError("data must contain at most 200 labelled finite non-negative values"); - values = data.map((row) => ({ - label: row.label, - value: row.value - })); - svg.replaceChildren(); - tbody.replaceChildren(); - const ns = "http://www.w3.org/2000/svg"; - const group = root.ownerDocument.createElementNS(ns, "g"); - group.setAttribute("class", "chart-series"); - svg.append(group); - const width = Math.max(300, values.length * 32), max = Math.max(1, ...values.map((row) => row.value)); - svg.setAttribute("viewBox", `0 0 ${width} 140`); - svg.setAttribute("aria-label", values.length ? values.map((row) => `${row.label}: ${row.value}`).join("; ") : "No data available"); - for (const [index, row] of values.entries()) { - const bar = root.ownerDocument.createElementNS(ns, "rect"), step = (width - 20) / values.length, height = row.value / max * 100; - for (const [name, value] of Object.entries({ - x: 10 + index * step + step * .15, - y: 110 - height, - width: step * .7, - height - })) bar.setAttribute(name, String(value)); - const title = root.ownerDocument.createElementNS(ns, "title"); - title.textContent = `${row.label}: ${row.value}`; - bar.append(title); - group.append(bar); - const tr = make(root, "tr"); - tr.append(make(root, "th", { scope: "row" }, row.label), make(root, "td", {}, row.value)); - tbody.append(tr); - } - svg.toggleAttribute("hidden", !values.length); - const empty = figure.querySelector("[data-chart-empty]"); - if (empty) empty.hidden = values.length !== 0; - }; - return { - get data() { - return values.map((row) => ({ ...row })); - }, - set data(data) { - update(data); - } - }; -} -function editorSearch(root, { on }) { - const input = root.querySelector("[data-query]"), pre = root.querySelector("[data-source]"), status = root.querySelector("[data-search-status]"); - if (!input || !pre) return {}; - let source = pre.textContent, current = -1, matches = []; - const previous = root.querySelector("[data-previous]"), following = root.querySelector("[data-next]"); - const select = (index) => { - current = matches.length ? (index + matches.length) % matches.length : -1; - all(pre, "mark").forEach((mark, i) => mark.toggleAttribute("data-current", i === current)); - if (status) status.textContent = !input.value ? "Enter text to search." : matches.length ? `Match ${current + 1} of ${matches.length}` : "No matches."; - }; - const search = () => { - matches = []; - pre.replaceChildren(); - const query = input.value.toLocaleLowerCase(); - let folded = "", offset = 0; - const starts = [], ends = []; - for (const char of source) { - const text = char.toLocaleLowerCase(); - for (let i = 0; i < text.length; i++) { - starts.push(offset); - ends.push(offset + char.length); - } - folded += text; - offset += char.length; - } - if (query) { - let position = 0; - while ((position = folded.indexOf(query, position)) >= 0) { - const start = starts[position], end = ends[position + query.length - 1]; - if (!matches.length || start >= matches.at(-1).end) matches.push({ - start, - end - }); - position += query.length; - } - } - let cursor = 0; - for (const match of matches) { - pre.append(root.ownerDocument.createTextNode(source.slice(cursor, match.start)), make(root, "mark", {}, source.slice(match.start, match.end))); - cursor = match.end; - } - pre.append(root.ownerDocument.createTextNode(source.slice(cursor))); - if (previous) previous.disabled = !matches.length; - if (following) following.disabled = !matches.length; - select(0); - }; - const next = (direction = 1) => { - if (!matches.length) return; - select(current + (direction < 0 ? -1 : 1)); - all(pre, "mark")[current]?.scrollIntoView({ - block: "nearest", - inline: "nearest" - }); - }; - on(input, "input", search); - on(input, "keydown", (event) => { - if (event.key === "Enter") { - event.preventDefault(); - next(event.shiftKey ? -1 : 1); - } else if (event.key === "Escape" && input.value) { - event.preventDefault(); - event.stopPropagation(); - input.value = ""; - search(); - } - }); - on(previous, "click", () => next(-1)); - on(following, "click", () => next()); - search(); - return { - next, - get source() { - return source; - }, - set source(text) { - source = String(text); - search(); - }, - get query() { - return input.value; - }, - set query(value) { - input.value = String(value); - search(); - }, - get matchCount() { - return matches.length; - } - }; -} -function developerView(root, { on }) { - on(root, "click", (event) => { - const action = event.target.closest("button,[data-action]"); - if (action && enabled(action)) root.emit("action", { action: action.dataset.action ?? action.textContent.trim() }); - }); - return { setText(text) { - let pre = root.querySelector("pre"); - if (!pre) { - pre = make(root, "pre", { - class: "j3w1-readonly-text", - tabindex: "0", - "aria-label": "Read-only text" - }); - root.firstElementChild.replaceChildren(pre); - } - pre.textContent = String(text); - } }; -} -//#endregion -export { editorSearch as i, chart as n, developerView as r, avatar as t }; diff --git a/packages/ui/dist/copy/editor-search/runtime/chunks/display-l54fb8vw.js b/packages/ui/dist/copy/editor-search/runtime/chunks/display-l54fb8vw.js new file mode 100644 index 000000000..b2f57aaf2 --- /dev/null +++ b/packages/ui/dist/copy/editor-search/runtime/chunks/display-l54fb8vw.js @@ -0,0 +1,211 @@ +import { i as all, l as make, o as enabled } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/display.js +function avatar(root, { on }) { + const frame = root.querySelector(".avatar"), fallback = root.querySelector("[data-avatar-fallback]"); + if (!frame || !fallback) return {}; + let image = frame.querySelector("img"); + if (!image) { + image = make(root, "img", { + alt: "", + hidden: "" + }); + frame.prepend(image); + } + let source = image.getAttribute("src") ?? ""; + const update = (value) => { + source = String(value ?? ""); + image.hidden = true; + fallback.hidden = false; + delete frame.dataset.error; + if (!source) { + image.removeAttribute("src"); + delete frame.dataset.loading; + return; + } + frame.dataset.loading = "true"; + image.src = source; + }; + on(image, "load", () => { + delete frame.dataset.loading; + image.hidden = false; + fallback.hidden = true; + }); + on(image, "error", () => { + delete frame.dataset.loading; + frame.dataset.error = "true"; + image.hidden = true; + fallback.hidden = false; + }); + update(root.getAttribute("src") ?? source); + return { + get src() { + return source; + }, + set src(value) { + update(value); + }, + attributeChanged(name) { + if (name === "src") update(root.getAttribute("src")); + } + }; +} +function chart(root) { + const figure = root.querySelector("figure"), svg = figure?.querySelector("svg"), tbody = figure?.querySelector("tbody"); + if (!figure || !svg || !tbody) return {}; + let values = all(tbody, "tr").map((row) => ({ + label: row.cells[0]?.textContent.trim() ?? "", + value: Number(row.cells[1]?.textContent) + })); + const update = (data) => { + if (!Array.isArray(data) || data.length > 200 || data.some((row) => typeof row.label !== "string" || typeof row.value !== "number" || !Number.isFinite(row.value) || row.value < 0)) throw new TypeError("data must contain at most 200 labelled finite non-negative values"); + values = data.map((row) => ({ + label: row.label, + value: row.value + })); + svg.replaceChildren(); + tbody.replaceChildren(); + const ns = "http://www.w3.org/2000/svg"; + const group = root.ownerDocument.createElementNS(ns, "g"); + group.setAttribute("class", "chart-series"); + svg.append(group); + const width = Math.max(300, values.length * 32), max = Math.max(1, ...values.map((row) => row.value)); + svg.setAttribute("viewBox", `0 0 ${width} 140`); + svg.setAttribute("aria-label", values.length ? values.map((row) => `${row.label}: ${row.value}`).join("; ") : "No data available"); + for (const [index, row] of values.entries()) { + const bar = root.ownerDocument.createElementNS(ns, "rect"), step = (width - 20) / values.length, height = row.value / max * 100; + for (const [name, value] of Object.entries({ + x: 10 + index * step + step * .15, + y: 110 - height, + width: step * .7, + height + })) bar.setAttribute(name, String(value)); + const title = root.ownerDocument.createElementNS(ns, "title"); + title.textContent = `${row.label}: ${row.value}`; + bar.append(title); + group.append(bar); + const tr = make(root, "tr"); + tr.append(make(root, "th", { scope: "row" }, row.label), make(root, "td", {}, row.value)); + tbody.append(tr); + } + svg.toggleAttribute("hidden", !values.length); + const empty = figure.querySelector("[data-chart-empty]"); + if (empty) empty.hidden = values.length !== 0; + }; + return { + get data() { + return values.map((row) => ({ ...row })); + }, + set data(data) { + update(data); + } + }; +} +function editorSearch(root, { on }) { + const input = root.querySelector("[data-query]"), pre = root.querySelector("[data-source]"), status = root.querySelector("[data-search-status]"); + if (!input || !pre) return {}; + let source = pre.textContent, current = -1, matches = []; + const previous = root.querySelector("[data-previous]"), following = root.querySelector("[data-next]"); + const select = (index) => { + current = matches.length ? (index + matches.length) % matches.length : -1; + all(pre, "mark").forEach((mark, i) => mark.toggleAttribute("data-current", i === current)); + if (status) status.textContent = !input.value ? "Enter text to search." : matches.length ? `Match ${current + 1} of ${matches.length}` : "No matches."; + }; + const search = () => { + matches = []; + pre.replaceChildren(); + const query = input.value.toLocaleLowerCase(); + let folded = "", offset = 0; + const starts = [], ends = []; + for (const char of source) { + const text = char.toLocaleLowerCase(); + for (let i = 0; i < text.length; i++) { + starts.push(offset); + ends.push(offset + char.length); + } + folded += text; + offset += char.length; + } + if (query) { + let position = 0; + while ((position = folded.indexOf(query, position)) >= 0) { + const start = starts[position], end = ends[position + query.length - 1]; + if (!matches.length || start >= matches.at(-1).end) matches.push({ + start, + end + }); + position += query.length; + } + } + let cursor = 0; + for (const match of matches) { + pre.append(root.ownerDocument.createTextNode(source.slice(cursor, match.start)), make(root, "mark", {}, source.slice(match.start, match.end))); + cursor = match.end; + } + pre.append(root.ownerDocument.createTextNode(source.slice(cursor))); + if (previous) previous.disabled = !matches.length; + if (following) following.disabled = !matches.length; + select(0); + }; + const next = (direction = 1) => { + if (!matches.length) return; + select(current + (direction < 0 ? -1 : 1)); + all(pre, "mark")[current]?.scrollIntoView({ + block: "nearest", + inline: "nearest" + }); + }; + on(input, "input", search); + on(input, "keydown", (event) => { + if (event.key === "Enter") { + event.preventDefault(); + next(event.shiftKey ? -1 : 1); + } else if (event.key === "Escape" && input.value) { + event.preventDefault(); + event.stopPropagation(); + input.value = ""; + search(); + } + }); + on(previous, "click", () => next(-1)); + on(following, "click", () => next()); + search(); + return { + next, + get source() { + return source; + }, + set source(text) { + source = String(text); + search(); + }, + get query() { + return input.value; + }, + set query(value) { + input.value = String(value); + search(); + }, + get matchCount() { + return matches.length; + } + }; +} +function developerView(root, { on }) { + on(root, "click", (event) => { + const action = event.target.closest("button,[data-action]"); + if (action && enabled(action)) root.emit("action", { action: action.dataset.action ?? action.textContent.trim() }); + }); + return { setText(text) { + let pre = root.querySelector("pre"); + if (!pre) { + pre = make(root, "pre", { + class: "j3w1-readonly-text", + tabindex: "0", + "aria-label": "Read-only text" + }); + root.firstElementChild.replaceChildren(pre); + } + pre.textContent = String(text); + } }; +} +export { editorSearch as i, chart as n, developerView as r, avatar as t }; diff --git a/packages/ui/dist/copy/editor-search/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/editor-search/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/editor-search/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/editor-search/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/editor-search/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/editor-search/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/editor-search/runtime/components/editor-search.js b/packages/ui/dist/copy/editor-search/runtime/components/editor-search.js index fc6e2a1a7..05e2f472e 100644 --- a/packages/ui/dist/copy/editor-search/runtime/components/editor-search.js +++ b/packages/ui/dist/copy/editor-search/runtime/components/editor-search.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { i as editorSearch } from "../chunks/display-Jm9bAsnb.js"; -//#region .cache/ui-build/entries/components/editor-search.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { i as editorSearch } from "../chunks/display-l54fb8vw.js"; +// .cache/ui-build/entries/components/editor-search.js var J3w1EditorSearch = class extends J3w1Element { static componentId = "editor-search"; static version = "4.0.0"; - static implementationId = "sha256-SqX6iBMRHKvfYM9+QKkc2K/hjCGRNMeVrj+B25L3SoU="; + static implementationId = "sha256-2urZm4vBPYuucwiyIFwjQWGpodxpGnr7FqeCciyKT3M="; static connect = editorSearch; static upgradeProperties = [ "disabled", @@ -43,5 +43,4 @@ var J3w1EditorSearch = class extends J3w1Element { return this._api?.matchCount; } }; -//#endregion export { J3w1EditorSearch }; diff --git a/packages/ui/dist/copy/editor-search/runtime/register/editor-search.js b/packages/ui/dist/copy/editor-search/runtime/register/editor-search.js index e0237ca4a..c06a4e9af 100644 --- a/packages/ui/dist/copy/editor-search/runtime/register/editor-search.js +++ b/packages/ui/dist/copy/editor-search/runtime/register/editor-search.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1EditorSearch } from "../components/editor-search.js"; -//#region .cache/ui-build/entries/register/editor-search.js +// .cache/ui-build/entries/register/editor-search.js var element = registerElement("j3w1-editor-search", J3w1EditorSearch); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/empty-state/manifest.json b/packages/ui/dist/copy/empty-state/manifest.json index 6bc41f49a..b95cbad6c 100644 --- a/packages/ui/dist/copy/empty-state/manifest.json +++ b/packages/ui/dist/copy/empty-state/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/empty-state.md", "dependencies": [ "register/empty-state.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/empty-state.js", - "chunks/overlays-BwgpF4jI.js" + "chunks/overlays-BW66WXLm.js" ], "files": { - "runtime/register/empty-state.js": "sha256-O+XPQiZJD3SM6EGCJ9p7Ia3RwHie8uDXVlJd2Vl8f1g=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/empty-state.js": "sha256-+Vgad2O/oKiGnSsGD63zlNKxCzqpHWhZ85dwct4yBx8=", - "runtime/chunks/overlays-BwgpF4jI.js": "sha256-NAd99OT4kDsFp8IHscKRus2jY6XRsq+GMzplWbJsY4U=", + "runtime/register/empty-state.js": "sha256-dB0amDn9V/in58Egc89rJ/1PCddeEm7h/pF3stAKhXo=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/empty-state.js": "sha256-4YkbuqMtIaxwQuQSzV4W2x18ZCoezW1TwANoDpPK3aQ=", + "runtime/chunks/overlays-BW66WXLm.js": "sha256-Z9etmUpuDuykKbJkriLMz8iiYnOP9uMUAshKwoHc1I8=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-BeQzoBMmZ//SCPym1JhwPfMM51a6wiO3oVtwH7lOOpc=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/empty-state/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/empty-state/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/empty-state/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/empty-state/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/empty-state/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/empty-state/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/empty-state/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/empty-state/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/empty-state/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/empty-state/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/empty-state/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/empty-state/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/empty-state/runtime/chunks/overlays-BW66WXLm.js b/packages/ui/dist/copy/empty-state/runtime/chunks/overlays-BW66WXLm.js new file mode 100644 index 000000000..d05c73b46 --- /dev/null +++ b/packages/ui/dist/copy/empty-state/runtime/chunks/overlays-BW66WXLm.js @@ -0,0 +1,244 @@ +import { d as place, i as all, o as enabled, s as identify } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/overlays.js +function modal(root, { on }) { + const dialog = root.querySelector("dialog"); + if (!dialog) return {}; + let opener = null; + const show = (trigger = root.ownerDocument.activeElement) => { + if (dialog.open || root.hasAttribute("disabled")) return; + opener = trigger; + dialog.showModal(); + (dialog.querySelector("[autofocus]") ?? dialog.querySelector("button:not(.dialog-button-destructive)"))?.focus(); + root.emit("open", {}); + }; + const close = (value = "") => { + if (dialog.open) dialog.close(String(value)); + }; + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (button?.matches("[data-open]")) { + show(button); + return; + } + if (button && dialog.contains(button) && enabled(button)) { + if (button.matches("[data-close],.dialog-close,.drawer-close")) close(button.dataset.close ?? "cancel"); + else if (button.dataset.action && root.emit("action", { action: button.dataset.action })) close(button.dataset.action); + } + if (root.constructor.componentId === "drawer" && event.target.closest("a[href]") && dialog.contains(event.target)) close("navigate"); + }); + on(dialog, "cancel", (event) => { + if (!root.emit("cancel", {})) event.preventDefault(); + }); + on(dialog, "close", () => { + if (opener?.isConnected) opener.focus(); + root.emit("close", { returnValue: dialog.returnValue }); + }); + return { + show, + close, + get open() { + return dialog.open; + }, + set open(value) { + value ? show() : close(); + }, + get returnValue() { + return dialog.returnValue; + }, + cleanup() { + if (dialog.open) dialog.close(); + } + }; +} +function tooltip(root, { on }) { + const trigger = root.querySelector(".tooltip-trigger"), popup = root.querySelector("[role=\"tooltip\"]"); + if (!trigger || !popup) return {}; + identify(root, popup, "tooltip"); + trigger.setAttribute("aria-describedby", popup.id); + let timer, hideTimer, dismissed = false, hovering = false; + const stop = () => { + clearTimeout(timer); + clearTimeout(hideTimer); + }; + const hide = () => { + stop(); + popup.hidden = true; + }; + const show = () => { + stop(); + if (!dismissed) { + popup.hidden = false; + place(trigger, popup); + } + }; + const hideSoon = () => { + clearTimeout(timer); + clearTimeout(hideTimer); + hideTimer = setTimeout(() => { + if (!hovering && root.ownerDocument.activeElement !== trigger) hide(); + }, 300); + }; + on(trigger, "pointerenter", (event) => { + if (event.pointerType !== "touch") { + hovering = true; + dismissed = false; + clearTimeout(hideTimer); + if (popup.hidden) timer = setTimeout(show, 300); + } + }); + on(root, "pointerleave", (event) => { + if (!root.contains(event.relatedTarget)) { + hovering = false; + dismissed = false; + if (root.ownerDocument.activeElement !== trigger) hideSoon(); + } + }); + on(popup, "pointerenter", () => { + hovering = true; + stop(); + }); + on(trigger, "focus", () => { + dismissed = false; + show(); + }); + on(trigger, "blur", () => { + if (!hovering) hide(); + }); + on(trigger, "click", () => { + dismissed = true; + hide(); + }); + on(trigger, "pointerdown", (event) => { + if (event.pointerType === "touch") { + dismissed = false; + timer = setTimeout(show, 500); + } + }); + on(trigger, "pointerup", stop); + on(trigger, "pointercancel", stop); + on(root.ownerDocument, "keydown", (event) => { + if (event.key === "Escape" && !popup.hidden) { + event.preventDefault(); + event.stopImmediatePropagation(); + dismissed = true; + hide(); + } + }, { capture: true }); + on(root.ownerDocument, "scroll", () => { + if (!popup.hidden) place(trigger, popup); + }, { capture: true }); + on(root.ownerDocument.defaultView, "resize", () => { + if (!popup.hidden) place(trigger, popup); + }); + hide(); + return { + show, + hide, + get open() { + return !popup.hidden; + }, + cleanup: hide + }; +} +function popover(root, { on }) { + const trigger = root.querySelector("[data-popover-trigger]"), panel = root.querySelector("[data-popover-panel]"); + if (!trigger || !panel) return {}; + identify(root, panel, "popover"); + trigger.setAttribute("aria-controls", panel.id); + const native = typeof panel.showPopover === "function"; + if (native) { + panel.setAttribute("popover", "auto"); + panel.hidden = false; + } else panel.hidden = true; + let open = false; + const sync = (value) => { + open = value; + trigger.setAttribute("aria-expanded", String(value)); + root.emit("toggle", { expanded: value }); + }; + const show = () => { + if (open || !enabled(trigger)) return; + native ? panel.showPopover() : panel.hidden = false; + sync(true); + place(trigger, panel); + }; + const hide = (focus = false) => { + if (!open) return; + native ? panel.hidePopover() : panel.hidden = true; + sync(false); + if (focus) trigger.focus(); + }; + on(trigger, "click", () => open ? hide() : show()); + on(panel, "beforetoggle", (event) => { + open = event.newState === "open"; + trigger.setAttribute("aria-expanded", String(open)); + }); + on(panel, "click", (event) => { + if (event.target.closest("[data-close]")) hide(true); + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!native && !root.contains(event.target)) hide(); + }); + on(root, "keydown", (event) => { + if (event.key === "Escape" && open) { + event.preventDefault(); + event.stopPropagation(); + hide(true); + } + }); + on(root.ownerDocument.defaultView, "resize", () => { + if (open) place(trigger, panel); + }); + trigger.setAttribute("aria-expanded", "false"); + return { + show, + hide, + get open() { + return open; + }, + set open(value) { + value ? show() : hide(); + }, + cleanup() { + hide(); + } + }; +} +function feedback(root, { on }) { + const dismiss = (item) => { + if (!item || !root.emit("dismiss", { id: item.id })) return; + const hadFocus = item.contains(root.ownerDocument.activeElement); + const focusable = all(root.ownerDocument, "button,a[href],input,select,textarea,[tabindex='0']").filter((node) => enabled(node) && !node.closest("[hidden]")); + const currentIndex = focusable.indexOf(root.ownerDocument.activeElement); + const next = focusable.slice(currentIndex + 1).find((node) => !item.contains(node)) ?? focusable.slice(0, currentIndex).reverse().find((node) => !item.contains(node)); + item.hidden = true; + if (hadFocus) next?.focus(); + }; + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button)) return; + if (button.matches(".toast-close,.alert-close,.chip-remove,[data-dismiss]")) dismiss(button.closest(".toast,.alert,.chip") ?? root); + else if (button.matches(".chip-filter")) { + button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + root.emit("action", { + action: button.textContent.trim(), + pressed: button.getAttribute("aria-pressed") === "true" + }); + } else if (button.matches("[data-retry]")) root.emit("retry", {}); + else root.emit("action", { action: button.dataset.action ?? button.textContent.trim() }); + }); + on(root, "keydown", (event) => { + if (event.key === "Escape") { + const toast = event.target.closest(".toast"); + if (toast) { + event.preventDefault(); + event.stopPropagation(); + dismiss(toast); + } + } + }); + return { dismiss(id) { + dismiss(id ? root.querySelector(`#${CSS.escape(id)}`) : root.querySelector(".toast,.alert") ?? root); + } }; +} +export { tooltip as i, modal as n, popover as r, feedback as t }; diff --git a/packages/ui/dist/copy/empty-state/runtime/chunks/overlays-BwgpF4jI.js b/packages/ui/dist/copy/empty-state/runtime/chunks/overlays-BwgpF4jI.js deleted file mode 100644 index 4b8de2e8b..000000000 --- a/packages/ui/dist/copy/empty-state/runtime/chunks/overlays-BwgpF4jI.js +++ /dev/null @@ -1,245 +0,0 @@ -import { d as place, i as all, o as enabled, s as identify } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/overlays.js -function modal(root, { on }) { - const dialog = root.querySelector("dialog"); - if (!dialog) return {}; - let opener = null; - const show = (trigger = root.ownerDocument.activeElement) => { - if (dialog.open || root.hasAttribute("disabled")) return; - opener = trigger; - dialog.showModal(); - (dialog.querySelector("[autofocus]") ?? dialog.querySelector("button:not(.dialog-button-destructive)"))?.focus(); - root.emit("open", {}); - }; - const close = (value = "") => { - if (dialog.open) dialog.close(String(value)); - }; - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (button?.matches("[data-open]")) { - show(button); - return; - } - if (button && dialog.contains(button) && enabled(button)) { - if (button.matches("[data-close],.dialog-close,.drawer-close")) close(button.dataset.close ?? "cancel"); - else if (button.dataset.action && root.emit("action", { action: button.dataset.action })) close(button.dataset.action); - } - if (root.constructor.componentId === "drawer" && event.target.closest("a[href]") && dialog.contains(event.target)) close("navigate"); - }); - on(dialog, "cancel", (event) => { - if (!root.emit("cancel", {})) event.preventDefault(); - }); - on(dialog, "close", () => { - if (opener?.isConnected) opener.focus(); - root.emit("close", { returnValue: dialog.returnValue }); - }); - return { - show, - close, - get open() { - return dialog.open; - }, - set open(value) { - value ? show() : close(); - }, - get returnValue() { - return dialog.returnValue; - }, - cleanup() { - if (dialog.open) dialog.close(); - } - }; -} -function tooltip(root, { on }) { - const trigger = root.querySelector(".tooltip-trigger"), popup = root.querySelector("[role=\"tooltip\"]"); - if (!trigger || !popup) return {}; - identify(root, popup, "tooltip"); - trigger.setAttribute("aria-describedby", popup.id); - let timer, hideTimer, dismissed = false, hovering = false; - const stop = () => { - clearTimeout(timer); - clearTimeout(hideTimer); - }; - const hide = () => { - stop(); - popup.hidden = true; - }; - const show = () => { - stop(); - if (!dismissed) { - popup.hidden = false; - place(trigger, popup); - } - }; - const hideSoon = () => { - clearTimeout(timer); - clearTimeout(hideTimer); - hideTimer = setTimeout(() => { - if (!hovering && root.ownerDocument.activeElement !== trigger) hide(); - }, 300); - }; - on(trigger, "pointerenter", (event) => { - if (event.pointerType !== "touch") { - hovering = true; - dismissed = false; - clearTimeout(hideTimer); - if (popup.hidden) timer = setTimeout(show, 300); - } - }); - on(root, "pointerleave", (event) => { - if (!root.contains(event.relatedTarget)) { - hovering = false; - dismissed = false; - if (root.ownerDocument.activeElement !== trigger) hideSoon(); - } - }); - on(popup, "pointerenter", () => { - hovering = true; - stop(); - }); - on(trigger, "focus", () => { - dismissed = false; - show(); - }); - on(trigger, "blur", () => { - if (!hovering) hide(); - }); - on(trigger, "click", () => { - dismissed = true; - hide(); - }); - on(trigger, "pointerdown", (event) => { - if (event.pointerType === "touch") { - dismissed = false; - timer = setTimeout(show, 500); - } - }); - on(trigger, "pointerup", stop); - on(trigger, "pointercancel", stop); - on(root.ownerDocument, "keydown", (event) => { - if (event.key === "Escape" && !popup.hidden) { - event.preventDefault(); - event.stopImmediatePropagation(); - dismissed = true; - hide(); - } - }, { capture: true }); - on(root.ownerDocument, "scroll", () => { - if (!popup.hidden) place(trigger, popup); - }, { capture: true }); - on(root.ownerDocument.defaultView, "resize", () => { - if (!popup.hidden) place(trigger, popup); - }); - hide(); - return { - show, - hide, - get open() { - return !popup.hidden; - }, - cleanup: hide - }; -} -function popover(root, { on }) { - const trigger = root.querySelector("[data-popover-trigger]"), panel = root.querySelector("[data-popover-panel]"); - if (!trigger || !panel) return {}; - identify(root, panel, "popover"); - trigger.setAttribute("aria-controls", panel.id); - const native = typeof panel.showPopover === "function"; - if (native) { - panel.setAttribute("popover", "auto"); - panel.hidden = false; - } else panel.hidden = true; - let open = false; - const sync = (value) => { - open = value; - trigger.setAttribute("aria-expanded", String(value)); - root.emit("toggle", { expanded: value }); - }; - const show = () => { - if (open || !enabled(trigger)) return; - native ? panel.showPopover() : panel.hidden = false; - sync(true); - place(trigger, panel); - }; - const hide = (focus = false) => { - if (!open) return; - native ? panel.hidePopover() : panel.hidden = true; - sync(false); - if (focus) trigger.focus(); - }; - on(trigger, "click", () => open ? hide() : show()); - on(panel, "beforetoggle", (event) => { - open = event.newState === "open"; - trigger.setAttribute("aria-expanded", String(open)); - }); - on(panel, "click", (event) => { - if (event.target.closest("[data-close]")) hide(true); - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!native && !root.contains(event.target)) hide(); - }); - on(root, "keydown", (event) => { - if (event.key === "Escape" && open) { - event.preventDefault(); - event.stopPropagation(); - hide(true); - } - }); - on(root.ownerDocument.defaultView, "resize", () => { - if (open) place(trigger, panel); - }); - trigger.setAttribute("aria-expanded", "false"); - return { - show, - hide, - get open() { - return open; - }, - set open(value) { - value ? show() : hide(); - }, - cleanup() { - hide(); - } - }; -} -function feedback(root, { on }) { - const dismiss = (item) => { - if (!item || !root.emit("dismiss", { id: item.id })) return; - const hadFocus = item.contains(root.ownerDocument.activeElement); - const focusable = all(root.ownerDocument, "button,a[href],input,select,textarea,[tabindex='0']").filter((node) => enabled(node) && !node.closest("[hidden]")); - const currentIndex = focusable.indexOf(root.ownerDocument.activeElement); - const next = focusable.slice(currentIndex + 1).find((node) => !item.contains(node)) ?? focusable.slice(0, currentIndex).reverse().find((node) => !item.contains(node)); - item.hidden = true; - if (hadFocus) next?.focus(); - }; - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button)) return; - if (button.matches(".toast-close,.alert-close,.chip-remove,[data-dismiss]")) dismiss(button.closest(".toast,.alert,.chip") ?? root); - else if (button.matches(".chip-filter")) { - button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - root.emit("action", { - action: button.textContent.trim(), - pressed: button.getAttribute("aria-pressed") === "true" - }); - } else if (button.matches("[data-retry]")) root.emit("retry", {}); - else root.emit("action", { action: button.dataset.action ?? button.textContent.trim() }); - }); - on(root, "keydown", (event) => { - if (event.key === "Escape") { - const toast = event.target.closest(".toast"); - if (toast) { - event.preventDefault(); - event.stopPropagation(); - dismiss(toast); - } - } - }); - return { dismiss(id) { - dismiss(id ? root.querySelector(`#${CSS.escape(id)}`) : root.querySelector(".toast,.alert") ?? root); - } }; -} -//#endregion -export { tooltip as i, modal as n, popover as r, feedback as t }; diff --git a/packages/ui/dist/copy/empty-state/runtime/components/empty-state.js b/packages/ui/dist/copy/empty-state/runtime/components/empty-state.js index 8e4944ef3..91d1cb423 100644 --- a/packages/ui/dist/copy/empty-state/runtime/components/empty-state.js +++ b/packages/ui/dist/copy/empty-state/runtime/components/empty-state.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as feedback } from "../chunks/overlays-BwgpF4jI.js"; -//#region .cache/ui-build/entries/components/empty-state.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as feedback } from "../chunks/overlays-BW66WXLm.js"; +// .cache/ui-build/entries/components/empty-state.js var J3w1EmptyState = class extends J3w1Element { static componentId = "empty-state"; static version = "4.0.0"; - static implementationId = "sha256-5BgPX4sRhOgm8ZsOZ/51exOqgz9E+QCMS8dKtOj0vGM="; + static implementationId = "sha256-0I18foHfPJW0lwhBhEhkVa29tFmqug1GlRB470z+Fc0="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -13,5 +13,4 @@ var J3w1EmptyState = class extends J3w1Element { return this._api.dismiss(...args); } }; -//#endregion export { J3w1EmptyState }; diff --git a/packages/ui/dist/copy/empty-state/runtime/register/empty-state.js b/packages/ui/dist/copy/empty-state/runtime/register/empty-state.js index a4b9594da..21cbfbeb4 100644 --- a/packages/ui/dist/copy/empty-state/runtime/register/empty-state.js +++ b/packages/ui/dist/copy/empty-state/runtime/register/empty-state.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1EmptyState } from "../components/empty-state.js"; -//#region .cache/ui-build/entries/register/empty-state.js +// .cache/ui-build/entries/register/empty-state.js var element = registerElement("j3w1-empty-state", J3w1EmptyState); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/error-state/manifest.json b/packages/ui/dist/copy/error-state/manifest.json index b28dc47f4..b3cf6cd79 100644 --- a/packages/ui/dist/copy/error-state/manifest.json +++ b/packages/ui/dist/copy/error-state/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/error-state.md", "dependencies": [ "register/error-state.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/error-state.js", - "chunks/overlays-BwgpF4jI.js" + "chunks/overlays-BW66WXLm.js" ], "files": { - "runtime/register/error-state.js": "sha256-7HAfC906Fv50aD7dtTHvGX8XoxDanaS7Xy+pD6+6JlQ=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/error-state.js": "sha256-BhughrbljbgIQKlE3iHBAZ5sfaZgHxDG49Pr3eO+qEA=", - "runtime/chunks/overlays-BwgpF4jI.js": "sha256-NAd99OT4kDsFp8IHscKRus2jY6XRsq+GMzplWbJsY4U=", + "runtime/register/error-state.js": "sha256-aJDvxh9+vUwd9iM93dBzHIYNHsvxbRWb+PWyrx/cUME=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/error-state.js": "sha256-oighlDczb4A0AuMh+nzeDiwSkUzdI1QF8Cq/NbkPlcs=", + "runtime/chunks/overlays-BW66WXLm.js": "sha256-Z9etmUpuDuykKbJkriLMz8iiYnOP9uMUAshKwoHc1I8=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-PkulOjRkq7PLGjfU346e4I1xzJqOFRjr9UgXNeugJLY=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/error-state/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/error-state/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/error-state/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/error-state/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/error-state/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/error-state/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/error-state/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/error-state/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/error-state/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/error-state/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/error-state/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/error-state/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/error-state/runtime/chunks/overlays-BW66WXLm.js b/packages/ui/dist/copy/error-state/runtime/chunks/overlays-BW66WXLm.js new file mode 100644 index 000000000..d05c73b46 --- /dev/null +++ b/packages/ui/dist/copy/error-state/runtime/chunks/overlays-BW66WXLm.js @@ -0,0 +1,244 @@ +import { d as place, i as all, o as enabled, s as identify } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/overlays.js +function modal(root, { on }) { + const dialog = root.querySelector("dialog"); + if (!dialog) return {}; + let opener = null; + const show = (trigger = root.ownerDocument.activeElement) => { + if (dialog.open || root.hasAttribute("disabled")) return; + opener = trigger; + dialog.showModal(); + (dialog.querySelector("[autofocus]") ?? dialog.querySelector("button:not(.dialog-button-destructive)"))?.focus(); + root.emit("open", {}); + }; + const close = (value = "") => { + if (dialog.open) dialog.close(String(value)); + }; + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (button?.matches("[data-open]")) { + show(button); + return; + } + if (button && dialog.contains(button) && enabled(button)) { + if (button.matches("[data-close],.dialog-close,.drawer-close")) close(button.dataset.close ?? "cancel"); + else if (button.dataset.action && root.emit("action", { action: button.dataset.action })) close(button.dataset.action); + } + if (root.constructor.componentId === "drawer" && event.target.closest("a[href]") && dialog.contains(event.target)) close("navigate"); + }); + on(dialog, "cancel", (event) => { + if (!root.emit("cancel", {})) event.preventDefault(); + }); + on(dialog, "close", () => { + if (opener?.isConnected) opener.focus(); + root.emit("close", { returnValue: dialog.returnValue }); + }); + return { + show, + close, + get open() { + return dialog.open; + }, + set open(value) { + value ? show() : close(); + }, + get returnValue() { + return dialog.returnValue; + }, + cleanup() { + if (dialog.open) dialog.close(); + } + }; +} +function tooltip(root, { on }) { + const trigger = root.querySelector(".tooltip-trigger"), popup = root.querySelector("[role=\"tooltip\"]"); + if (!trigger || !popup) return {}; + identify(root, popup, "tooltip"); + trigger.setAttribute("aria-describedby", popup.id); + let timer, hideTimer, dismissed = false, hovering = false; + const stop = () => { + clearTimeout(timer); + clearTimeout(hideTimer); + }; + const hide = () => { + stop(); + popup.hidden = true; + }; + const show = () => { + stop(); + if (!dismissed) { + popup.hidden = false; + place(trigger, popup); + } + }; + const hideSoon = () => { + clearTimeout(timer); + clearTimeout(hideTimer); + hideTimer = setTimeout(() => { + if (!hovering && root.ownerDocument.activeElement !== trigger) hide(); + }, 300); + }; + on(trigger, "pointerenter", (event) => { + if (event.pointerType !== "touch") { + hovering = true; + dismissed = false; + clearTimeout(hideTimer); + if (popup.hidden) timer = setTimeout(show, 300); + } + }); + on(root, "pointerleave", (event) => { + if (!root.contains(event.relatedTarget)) { + hovering = false; + dismissed = false; + if (root.ownerDocument.activeElement !== trigger) hideSoon(); + } + }); + on(popup, "pointerenter", () => { + hovering = true; + stop(); + }); + on(trigger, "focus", () => { + dismissed = false; + show(); + }); + on(trigger, "blur", () => { + if (!hovering) hide(); + }); + on(trigger, "click", () => { + dismissed = true; + hide(); + }); + on(trigger, "pointerdown", (event) => { + if (event.pointerType === "touch") { + dismissed = false; + timer = setTimeout(show, 500); + } + }); + on(trigger, "pointerup", stop); + on(trigger, "pointercancel", stop); + on(root.ownerDocument, "keydown", (event) => { + if (event.key === "Escape" && !popup.hidden) { + event.preventDefault(); + event.stopImmediatePropagation(); + dismissed = true; + hide(); + } + }, { capture: true }); + on(root.ownerDocument, "scroll", () => { + if (!popup.hidden) place(trigger, popup); + }, { capture: true }); + on(root.ownerDocument.defaultView, "resize", () => { + if (!popup.hidden) place(trigger, popup); + }); + hide(); + return { + show, + hide, + get open() { + return !popup.hidden; + }, + cleanup: hide + }; +} +function popover(root, { on }) { + const trigger = root.querySelector("[data-popover-trigger]"), panel = root.querySelector("[data-popover-panel]"); + if (!trigger || !panel) return {}; + identify(root, panel, "popover"); + trigger.setAttribute("aria-controls", panel.id); + const native = typeof panel.showPopover === "function"; + if (native) { + panel.setAttribute("popover", "auto"); + panel.hidden = false; + } else panel.hidden = true; + let open = false; + const sync = (value) => { + open = value; + trigger.setAttribute("aria-expanded", String(value)); + root.emit("toggle", { expanded: value }); + }; + const show = () => { + if (open || !enabled(trigger)) return; + native ? panel.showPopover() : panel.hidden = false; + sync(true); + place(trigger, panel); + }; + const hide = (focus = false) => { + if (!open) return; + native ? panel.hidePopover() : panel.hidden = true; + sync(false); + if (focus) trigger.focus(); + }; + on(trigger, "click", () => open ? hide() : show()); + on(panel, "beforetoggle", (event) => { + open = event.newState === "open"; + trigger.setAttribute("aria-expanded", String(open)); + }); + on(panel, "click", (event) => { + if (event.target.closest("[data-close]")) hide(true); + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!native && !root.contains(event.target)) hide(); + }); + on(root, "keydown", (event) => { + if (event.key === "Escape" && open) { + event.preventDefault(); + event.stopPropagation(); + hide(true); + } + }); + on(root.ownerDocument.defaultView, "resize", () => { + if (open) place(trigger, panel); + }); + trigger.setAttribute("aria-expanded", "false"); + return { + show, + hide, + get open() { + return open; + }, + set open(value) { + value ? show() : hide(); + }, + cleanup() { + hide(); + } + }; +} +function feedback(root, { on }) { + const dismiss = (item) => { + if (!item || !root.emit("dismiss", { id: item.id })) return; + const hadFocus = item.contains(root.ownerDocument.activeElement); + const focusable = all(root.ownerDocument, "button,a[href],input,select,textarea,[tabindex='0']").filter((node) => enabled(node) && !node.closest("[hidden]")); + const currentIndex = focusable.indexOf(root.ownerDocument.activeElement); + const next = focusable.slice(currentIndex + 1).find((node) => !item.contains(node)) ?? focusable.slice(0, currentIndex).reverse().find((node) => !item.contains(node)); + item.hidden = true; + if (hadFocus) next?.focus(); + }; + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button)) return; + if (button.matches(".toast-close,.alert-close,.chip-remove,[data-dismiss]")) dismiss(button.closest(".toast,.alert,.chip") ?? root); + else if (button.matches(".chip-filter")) { + button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + root.emit("action", { + action: button.textContent.trim(), + pressed: button.getAttribute("aria-pressed") === "true" + }); + } else if (button.matches("[data-retry]")) root.emit("retry", {}); + else root.emit("action", { action: button.dataset.action ?? button.textContent.trim() }); + }); + on(root, "keydown", (event) => { + if (event.key === "Escape") { + const toast = event.target.closest(".toast"); + if (toast) { + event.preventDefault(); + event.stopPropagation(); + dismiss(toast); + } + } + }); + return { dismiss(id) { + dismiss(id ? root.querySelector(`#${CSS.escape(id)}`) : root.querySelector(".toast,.alert") ?? root); + } }; +} +export { tooltip as i, modal as n, popover as r, feedback as t }; diff --git a/packages/ui/dist/copy/error-state/runtime/chunks/overlays-BwgpF4jI.js b/packages/ui/dist/copy/error-state/runtime/chunks/overlays-BwgpF4jI.js deleted file mode 100644 index 4b8de2e8b..000000000 --- a/packages/ui/dist/copy/error-state/runtime/chunks/overlays-BwgpF4jI.js +++ /dev/null @@ -1,245 +0,0 @@ -import { d as place, i as all, o as enabled, s as identify } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/overlays.js -function modal(root, { on }) { - const dialog = root.querySelector("dialog"); - if (!dialog) return {}; - let opener = null; - const show = (trigger = root.ownerDocument.activeElement) => { - if (dialog.open || root.hasAttribute("disabled")) return; - opener = trigger; - dialog.showModal(); - (dialog.querySelector("[autofocus]") ?? dialog.querySelector("button:not(.dialog-button-destructive)"))?.focus(); - root.emit("open", {}); - }; - const close = (value = "") => { - if (dialog.open) dialog.close(String(value)); - }; - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (button?.matches("[data-open]")) { - show(button); - return; - } - if (button && dialog.contains(button) && enabled(button)) { - if (button.matches("[data-close],.dialog-close,.drawer-close")) close(button.dataset.close ?? "cancel"); - else if (button.dataset.action && root.emit("action", { action: button.dataset.action })) close(button.dataset.action); - } - if (root.constructor.componentId === "drawer" && event.target.closest("a[href]") && dialog.contains(event.target)) close("navigate"); - }); - on(dialog, "cancel", (event) => { - if (!root.emit("cancel", {})) event.preventDefault(); - }); - on(dialog, "close", () => { - if (opener?.isConnected) opener.focus(); - root.emit("close", { returnValue: dialog.returnValue }); - }); - return { - show, - close, - get open() { - return dialog.open; - }, - set open(value) { - value ? show() : close(); - }, - get returnValue() { - return dialog.returnValue; - }, - cleanup() { - if (dialog.open) dialog.close(); - } - }; -} -function tooltip(root, { on }) { - const trigger = root.querySelector(".tooltip-trigger"), popup = root.querySelector("[role=\"tooltip\"]"); - if (!trigger || !popup) return {}; - identify(root, popup, "tooltip"); - trigger.setAttribute("aria-describedby", popup.id); - let timer, hideTimer, dismissed = false, hovering = false; - const stop = () => { - clearTimeout(timer); - clearTimeout(hideTimer); - }; - const hide = () => { - stop(); - popup.hidden = true; - }; - const show = () => { - stop(); - if (!dismissed) { - popup.hidden = false; - place(trigger, popup); - } - }; - const hideSoon = () => { - clearTimeout(timer); - clearTimeout(hideTimer); - hideTimer = setTimeout(() => { - if (!hovering && root.ownerDocument.activeElement !== trigger) hide(); - }, 300); - }; - on(trigger, "pointerenter", (event) => { - if (event.pointerType !== "touch") { - hovering = true; - dismissed = false; - clearTimeout(hideTimer); - if (popup.hidden) timer = setTimeout(show, 300); - } - }); - on(root, "pointerleave", (event) => { - if (!root.contains(event.relatedTarget)) { - hovering = false; - dismissed = false; - if (root.ownerDocument.activeElement !== trigger) hideSoon(); - } - }); - on(popup, "pointerenter", () => { - hovering = true; - stop(); - }); - on(trigger, "focus", () => { - dismissed = false; - show(); - }); - on(trigger, "blur", () => { - if (!hovering) hide(); - }); - on(trigger, "click", () => { - dismissed = true; - hide(); - }); - on(trigger, "pointerdown", (event) => { - if (event.pointerType === "touch") { - dismissed = false; - timer = setTimeout(show, 500); - } - }); - on(trigger, "pointerup", stop); - on(trigger, "pointercancel", stop); - on(root.ownerDocument, "keydown", (event) => { - if (event.key === "Escape" && !popup.hidden) { - event.preventDefault(); - event.stopImmediatePropagation(); - dismissed = true; - hide(); - } - }, { capture: true }); - on(root.ownerDocument, "scroll", () => { - if (!popup.hidden) place(trigger, popup); - }, { capture: true }); - on(root.ownerDocument.defaultView, "resize", () => { - if (!popup.hidden) place(trigger, popup); - }); - hide(); - return { - show, - hide, - get open() { - return !popup.hidden; - }, - cleanup: hide - }; -} -function popover(root, { on }) { - const trigger = root.querySelector("[data-popover-trigger]"), panel = root.querySelector("[data-popover-panel]"); - if (!trigger || !panel) return {}; - identify(root, panel, "popover"); - trigger.setAttribute("aria-controls", panel.id); - const native = typeof panel.showPopover === "function"; - if (native) { - panel.setAttribute("popover", "auto"); - panel.hidden = false; - } else panel.hidden = true; - let open = false; - const sync = (value) => { - open = value; - trigger.setAttribute("aria-expanded", String(value)); - root.emit("toggle", { expanded: value }); - }; - const show = () => { - if (open || !enabled(trigger)) return; - native ? panel.showPopover() : panel.hidden = false; - sync(true); - place(trigger, panel); - }; - const hide = (focus = false) => { - if (!open) return; - native ? panel.hidePopover() : panel.hidden = true; - sync(false); - if (focus) trigger.focus(); - }; - on(trigger, "click", () => open ? hide() : show()); - on(panel, "beforetoggle", (event) => { - open = event.newState === "open"; - trigger.setAttribute("aria-expanded", String(open)); - }); - on(panel, "click", (event) => { - if (event.target.closest("[data-close]")) hide(true); - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!native && !root.contains(event.target)) hide(); - }); - on(root, "keydown", (event) => { - if (event.key === "Escape" && open) { - event.preventDefault(); - event.stopPropagation(); - hide(true); - } - }); - on(root.ownerDocument.defaultView, "resize", () => { - if (open) place(trigger, panel); - }); - trigger.setAttribute("aria-expanded", "false"); - return { - show, - hide, - get open() { - return open; - }, - set open(value) { - value ? show() : hide(); - }, - cleanup() { - hide(); - } - }; -} -function feedback(root, { on }) { - const dismiss = (item) => { - if (!item || !root.emit("dismiss", { id: item.id })) return; - const hadFocus = item.contains(root.ownerDocument.activeElement); - const focusable = all(root.ownerDocument, "button,a[href],input,select,textarea,[tabindex='0']").filter((node) => enabled(node) && !node.closest("[hidden]")); - const currentIndex = focusable.indexOf(root.ownerDocument.activeElement); - const next = focusable.slice(currentIndex + 1).find((node) => !item.contains(node)) ?? focusable.slice(0, currentIndex).reverse().find((node) => !item.contains(node)); - item.hidden = true; - if (hadFocus) next?.focus(); - }; - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button)) return; - if (button.matches(".toast-close,.alert-close,.chip-remove,[data-dismiss]")) dismiss(button.closest(".toast,.alert,.chip") ?? root); - else if (button.matches(".chip-filter")) { - button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - root.emit("action", { - action: button.textContent.trim(), - pressed: button.getAttribute("aria-pressed") === "true" - }); - } else if (button.matches("[data-retry]")) root.emit("retry", {}); - else root.emit("action", { action: button.dataset.action ?? button.textContent.trim() }); - }); - on(root, "keydown", (event) => { - if (event.key === "Escape") { - const toast = event.target.closest(".toast"); - if (toast) { - event.preventDefault(); - event.stopPropagation(); - dismiss(toast); - } - } - }); - return { dismiss(id) { - dismiss(id ? root.querySelector(`#${CSS.escape(id)}`) : root.querySelector(".toast,.alert") ?? root); - } }; -} -//#endregion -export { tooltip as i, modal as n, popover as r, feedback as t }; diff --git a/packages/ui/dist/copy/error-state/runtime/components/error-state.js b/packages/ui/dist/copy/error-state/runtime/components/error-state.js index 304fd3e2b..cbf702503 100644 --- a/packages/ui/dist/copy/error-state/runtime/components/error-state.js +++ b/packages/ui/dist/copy/error-state/runtime/components/error-state.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as feedback } from "../chunks/overlays-BwgpF4jI.js"; -//#region .cache/ui-build/entries/components/error-state.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as feedback } from "../chunks/overlays-BW66WXLm.js"; +// .cache/ui-build/entries/components/error-state.js var J3w1ErrorState = class extends J3w1Element { static componentId = "error-state"; static version = "4.0.0"; - static implementationId = "sha256-tOUjSBC5VAWfv+AicnePxVZaKItd4HUgjbSSn0EAnj4="; + static implementationId = "sha256-LDQJ+yUJQFusNMFvRdiX+9xXps1b5gKkDGOIKUsi3is="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -13,5 +13,4 @@ var J3w1ErrorState = class extends J3w1Element { return this._api.dismiss(...args); } }; -//#endregion export { J3w1ErrorState }; diff --git a/packages/ui/dist/copy/error-state/runtime/register/error-state.js b/packages/ui/dist/copy/error-state/runtime/register/error-state.js index 5e09ece1b..033288151 100644 --- a/packages/ui/dist/copy/error-state/runtime/register/error-state.js +++ b/packages/ui/dist/copy/error-state/runtime/register/error-state.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1ErrorState } from "../components/error-state.js"; -//#region .cache/ui-build/entries/register/error-state.js +// .cache/ui-build/entries/register/error-state.js var element = registerElement("j3w1-error-state", J3w1ErrorState); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/field/manifest.json b/packages/ui/dist/copy/field/manifest.json index dcfa893ab..82c84d944 100644 --- a/packages/ui/dist/copy/field/manifest.json +++ b/packages/ui/dist/copy/field/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/field.md", "dependencies": [ "register/field.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/field.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/field.js": "sha256-zLQtzqVvRVMiR9nicBMgkx8zeeoejrZolk/zDj6Q1Q4=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/field.js": "sha256-ummTNywyrj12MoNMHDD5qiPFCif8xG24RwdhXXF7LnU=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/field.js": "sha256-idnG0SIbXzZPGP1U3H9jFyhEUzotK2gRMKB/6ZZQQLo=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/field.js": "sha256-7DL5f/G9uaZueJ05MP0+CoD5fXGcX5gl7rU5qy2lAZg=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-NdGAWLleLWawKN47P/spgrR/kdjbB/c8l7xBXcLxIoI=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/field/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/field/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/field/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/field/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/field/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/field/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/field/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/field/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/field/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/field/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/field/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/field/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/field/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/field/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/field/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/field/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/field/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/field/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/field/runtime/components/field.js b/packages/ui/dist/copy/field/runtime/components/field.js index 432885b11..22f6586d6 100644 --- a/packages/ui/dist/copy/field/runtime/components/field.js +++ b/packages/ui/dist/copy/field/runtime/components/field.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/field.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/field.js var J3w1Field = class extends J3w1Element { static componentId = "field"; static version = "4.0.0"; - static implementationId = "sha256-GDPT/9zMxdyqVusrML6KYJd3mC9Kts0/5zp2/Xi2cYA="; + static implementationId = "sha256-24nMRMLzw+GWacRUm+Sql7UXZ+F7xi0oVvrBEXq9G0o="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Field }; diff --git a/packages/ui/dist/copy/field/runtime/register/field.js b/packages/ui/dist/copy/field/runtime/register/field.js index 875540d71..a70ac0aec 100644 --- a/packages/ui/dist/copy/field/runtime/register/field.js +++ b/packages/ui/dist/copy/field/runtime/register/field.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Field } from "../components/field.js"; -//#region .cache/ui-build/entries/register/field.js +// .cache/ui-build/entries/register/field.js var element = registerElement("j3w1-field", J3w1Field); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/fieldset/manifest.json b/packages/ui/dist/copy/fieldset/manifest.json index 3a821fd52..ffff79c8c 100644 --- a/packages/ui/dist/copy/fieldset/manifest.json +++ b/packages/ui/dist/copy/fieldset/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/fieldset.md", "dependencies": [ "register/fieldset.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/fieldset.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/fieldset.js": "sha256-o9TJ39JjoD9lKj18M0HEJIsEaXvxYLuKg0BameLC9rQ=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/fieldset.js": "sha256-NnApETrqjlE4MbJmLICen1VVGenfbkiqjiNh9jSLgF8=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/fieldset.js": "sha256-zuT5rtNl3t8k1HJk1X7Q3lQIAgyzKBUsKFZPD0E/ihc=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/fieldset.js": "sha256-TWSyWZNRKgfnqI8T6d1EQ5W/mD6n0d8CqqP8ZNXAKgw=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-8VS+tXfjHW87aIScNUGAXsrsJ0qwScONidsZFMMFNh0=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/fieldset/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/fieldset/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/fieldset/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/fieldset/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/fieldset/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/fieldset/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/fieldset/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/fieldset/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/fieldset/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/fieldset/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/fieldset/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/fieldset/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/fieldset/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/fieldset/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/fieldset/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/fieldset/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/fieldset/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/fieldset/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/fieldset/runtime/components/fieldset.js b/packages/ui/dist/copy/fieldset/runtime/components/fieldset.js index 062960dc4..a37eb3884 100644 --- a/packages/ui/dist/copy/fieldset/runtime/components/fieldset.js +++ b/packages/ui/dist/copy/fieldset/runtime/components/fieldset.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/fieldset.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/fieldset.js var J3w1Fieldset = class extends J3w1Element { static componentId = "fieldset"; static version = "4.0.0"; - static implementationId = "sha256-GMEsNCLKXzxBWy1NzvLrpSNVUG/llwSmGqxbUbScbHQ="; + static implementationId = "sha256-RPx5oBBUk/CP7P0+MjMH+Vlv++S2aNxlNzAivfeo8MY="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Fieldset }; diff --git a/packages/ui/dist/copy/fieldset/runtime/register/fieldset.js b/packages/ui/dist/copy/fieldset/runtime/register/fieldset.js index 4ac632e86..01a3ded77 100644 --- a/packages/ui/dist/copy/fieldset/runtime/register/fieldset.js +++ b/packages/ui/dist/copy/fieldset/runtime/register/fieldset.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Fieldset } from "../components/fieldset.js"; -//#region .cache/ui-build/entries/register/fieldset.js +// .cache/ui-build/entries/register/fieldset.js var element = registerElement("j3w1-fieldset", J3w1Fieldset); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/file-browser/manifest.json b/packages/ui/dist/copy/file-browser/manifest.json index e36776092..e20d6b897 100644 --- a/packages/ui/dist/copy/file-browser/manifest.json +++ b/packages/ui/dist/copy/file-browser/manifest.json @@ -5,27 +5,27 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/file-browser.md", "dependencies": [ "register/file-browser.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "register/tree.js", "components/tree.js", - "chunks/advanced-CqBF0dSb.js", - "chunks/markup-DeQ4bEMR.js", + "chunks/advanced-BrFnVc0y.js", + "chunks/markup-AopKpwOF.js", "components/file-browser.js", - "chunks/compositions-D57dCsBz.js", - "chunks/navigation-BfNzDYZB.js" + "chunks/compositions-DWG4tv9E.js", + "chunks/navigation-CknoksQ5.js" ], "files": { - "runtime/register/file-browser.js": "sha256-6aZxofgHXmaSyrN62aRqrgBNsgXkVl76hwSUGwzsxpM=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/register/tree.js": "sha256-5FC2B/6Dr2k5l/nTb9KKizslYbXmQxe2nEoLuYG6zDg=", - "runtime/components/tree.js": "sha256-mYl4DYRuChSjXkRwM7LaJ31aYQZlvzP0RgTYmuNdC9U=", - "runtime/chunks/advanced-CqBF0dSb.js": "sha256-ozOzkRU6IeVGBqU3XQ0aLledkAi9vcs8dJdMQutVevs=", - "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", - "runtime/components/file-browser.js": "sha256-rX/Iibk2FD9zA2T7ojRVZgvx3P/v8vt8GOi0X/OOEOY=", - "runtime/chunks/compositions-D57dCsBz.js": "sha256-PEpI/vGgdD+LSznUd0iedSxxVE+5QxIO7BGKeQnCRjo=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", + "runtime/register/file-browser.js": "sha256-JGPbb5bwIfA5k1lkGmAD5MHW7FaEf/ACtTM2u/vPPbo=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/register/tree.js": "sha256-GkpgoR9dpb/ho4x6diQOMGUvBv63XZ0KfaibFjm74gA=", + "runtime/components/tree.js": "sha256-P+63dC5MB2gKl/raxboRMQBCkbmDE850SXCmGt09e/o=", + "runtime/chunks/advanced-BrFnVc0y.js": "sha256-FVberBpKO49P/WGnxa61BTxhYsLnnvMFInur/TwjG44=", + "runtime/chunks/markup-AopKpwOF.js": "sha256-/Dn3cWEmlRQzeQAPVf+C0AooVb1pdIQeNeqd1fQVoPc=", + "runtime/components/file-browser.js": "sha256-f7EdtKJccQxuUuP+3ZqlKg9dJhLkwcMrO9wF55ABqtU=", + "runtime/chunks/compositions-DWG4tv9E.js": "sha256-vV/UcQrj3UFpVXymFuH4t/h/T+7JqBeND9xuyVdCjqo=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-UxawfUHhz140JTldQCb8aDbVaLGRxrgbxNCkmCkXxmM=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/file-browser/runtime/chunks/advanced-CqBF0dSb.js b/packages/ui/dist/copy/file-browser/runtime/chunks/advanced-BrFnVc0y.js similarity index 98% rename from packages/ui/dist/copy/file-browser/runtime/chunks/advanced-CqBF0dSb.js rename to packages/ui/dist/copy/file-browser/runtime/chunks/advanced-BrFnVc0y.js index 4a5c45981..36e7638c4 100644 --- a/packages/ui/dist/copy/file-browser/runtime/chunks/advanced-CqBF0dSb.js +++ b/packages/ui/dist/copy/file-browser/runtime/chunks/advanced-BrFnVc0y.js @@ -1,6 +1,6 @@ -import { c as keyIndex, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-B7mo5Eq3.js"; -import { t as IDREFS } from "./markup-DeQ4bEMR.js"; -//#region packages/ui/src/behaviors/advanced.js +import { c as keyIndex, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-DqwWT5pJ.js"; +import { t as IDREFS } from "./markup-AopKpwOF.js"; +// packages/ui/src/behaviors/advanced.js function tree(root, { on }) { const treeRoot = root.querySelector("[role=\"tree\"]"); if (!treeRoot) return {}; @@ -341,5 +341,4 @@ function commandPalette(root, { on }) { cleanup: close }; } -//#endregion export { tree as i, multiselect as n, repeater as r, commandPalette as t }; diff --git a/packages/ui/dist/copy/file-browser/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/file-browser/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/file-browser/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/file-browser/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/file-browser/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/file-browser/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/chunks/compositions-D57dCsBz.js b/packages/ui/dist/copy/file-browser/runtime/chunks/compositions-DWG4tv9E.js similarity index 91% rename from packages/ui/dist/chunks/compositions-D57dCsBz.js rename to packages/ui/dist/copy/file-browser/runtime/chunks/compositions-DWG4tv9E.js index f1da4562e..aa98d384a 100644 --- a/packages/ui/dist/chunks/compositions-D57dCsBz.js +++ b/packages/ui/dist/copy/file-browser/runtime/chunks/compositions-DWG4tv9E.js @@ -1,6 +1,6 @@ -import { i as all, o as enabled } from "./choice-B7mo5Eq3.js"; -import { i as tabs } from "./navigation-BfNzDYZB.js"; -//#region packages/ui/src/behaviors/compositions.js +import { i as all, o as enabled } from "./choice-DqwWT5pJ.js"; +import { i as tabs } from "./navigation-CknoksQ5.js"; +// packages/ui/src/behaviors/compositions.js function fileBrowser(root, { on }) { const query = root.querySelector("[data-file-query]"), rows = all(root, "tr[data-file-id]"), status = root.querySelector("[data-file-status]"); let location = "all"; @@ -47,5 +47,4 @@ function windowFrame(root, context) { }); return {}; } -//#endregion export { fileBrowser as n, windowFrame as r, dashboard as t }; diff --git a/packages/ui/dist/copy/file-browser/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/file-browser/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/file-browser/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/file-browser/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/file-browser/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/file-browser/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/file-browser/runtime/chunks/markup-DeQ4bEMR.js b/packages/ui/dist/copy/file-browser/runtime/chunks/markup-AopKpwOF.js similarity index 97% rename from packages/ui/dist/copy/file-browser/runtime/chunks/markup-DeQ4bEMR.js rename to packages/ui/dist/copy/file-browser/runtime/chunks/markup-AopKpwOF.js index 77bd9471d..bc1c52c0b 100644 --- a/packages/ui/dist/copy/file-browser/runtime/chunks/markup-DeQ4bEMR.js +++ b/packages/ui/dist/copy/file-browser/runtime/chunks/markup-AopKpwOF.js @@ -1,4 +1,4 @@ -//#region scripts/lib/markup.mjs +// scripts/lib/markup.mjs var IDREFS = /* @__PURE__ */ new Set([ "for", "form", @@ -50,5 +50,4 @@ var namespaceMarkup = (tree, decorate, { strict = true, renameNames = false } = else if (renameNames && attr.name === "name") attr.value = decorate(attr.value); }); }; -//#endregion export { setAttribute as a, removeAttribute as i, hasClass as n, walkMarkup as o, namespaceMarkup as r, IDREFS as t }; diff --git a/packages/ui/dist/copy/file-browser/runtime/chunks/navigation-BfNzDYZB.js b/packages/ui/dist/copy/file-browser/runtime/chunks/navigation-BfNzDYZB.js deleted file mode 100644 index db2779553..000000000 --- a/packages/ui/dist/copy/file-browser/runtime/chunks/navigation-BfNzDYZB.js +++ /dev/null @@ -1,377 +0,0 @@ -import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/navigation.js -function tabs(root, { on }, listOverride) { - const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); - if (!list) return {}; - const items = () => all(list, "[role=\"tab\"]").filter(enabled); - const select = (id, focus = false) => { - const tab = items().find((item) => item.id === id); - if (!tab) throw new RangeError(`Unknown enabled tab: ${id}`); - all(list, "[role=\"tab\"]").forEach((item) => { - item.setAttribute("aria-selected", String(item === tab)); - item.tabIndex = item === tab ? 0 : -1; - }); - all(root, "[role=\"tabpanel\"]").filter((panel) => all(list, "[role=\"tab\"]").some((tab) => tab.getAttribute("aria-controls") === panel.id)).forEach((panel) => { - panel.hidden = panel.id !== tab.getAttribute("aria-controls"); - if (!panel.hidden && !panel.querySelector("a[href],button,input,select,textarea,[tabindex='0']")) panel.tabIndex = 0; - }); - if (focus) tab.focus(); - return tab; - }; - const activate = (tab) => { - select(tab.id); - root.emit("select", { - id: tab.id, - panelId: tab.getAttribute("aria-controls") - }); - }; - on(list, "click", (event) => { - const tab = event.target.closest("[role=\"tab\"]"); - if (tab && enabled(tab)) activate(tab); - }); - on(list, "keydown", (event) => { - const current = event.target.closest("[role=\"tab\"]"), options = items(); - if (!current) return; - const vertical = list.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(list).direction === "rtl"; - const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", previous = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; - let index = options.indexOf(current); - if (event.key === next) index++; - else if (event.key === previous) index--; - else if (event.key === "Home") index = 0; - else if (event.key === "End") index = options.length - 1; - else if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - activate(current); - return; - } else return; - event.preventDefault(); - const tab = rove(options, index); - if (root.getAttribute("activation") !== "manual") activate(tab); - }); - const initial = items().find((item) => item.getAttribute("aria-selected") === "true") ?? items()[0]; - if (initial) select(initial.id); - return { - select, - get selectedId() { - return list.querySelector("[aria-selected=\"true\"]")?.id ?? ""; - }, - set selectedId(id) { - select(id); - } - }; -} -function toolbar(root, { on }) { - const bar = root.querySelector("[role=\"toolbar\"]"); - if (!bar) return {}; - const controls = () => all(bar, "button,a[href],input,select").filter((node) => enabled(node) && visible(node) && !node.closest("[role=\"menu\"]")); - const initial = controls(); - rove(initial, Math.max(0, initial.findIndex((node) => node.tabIndex === 0)), false); - on(bar, "focusin", (event) => { - if (controls().includes(event.target)) rove(controls(), controls().indexOf(event.target), false); - }); - on(bar, "keydown", (event) => { - if (event.target.matches("input,select,textarea") || event.target.closest("[role=\"menu\"]")) return; - const items = controls(), index = items.indexOf(event.target); - const vertical = bar.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(bar).direction === "rtl"; - const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", prev = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; - if (![ - next, - prev, - "Home", - "End" - ].includes(event.key)) return; - event.preventDefault(); - rove(items, keyIndex({ - key: event.key, - index, - length: items.length, - next, - previous: prev - })); - }); - on(bar, "click", (event) => { - const button = event.target.closest("button[aria-pressed]"); - if (button && enabled(button)) { - button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - root.emit("action", { - action: button.dataset.action ?? button.textContent.trim(), - pressed: button.getAttribute("aria-pressed") === "true" - }); - } - }); - return {}; -} -function disclosure(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button[aria-controls][aria-expanded]"); - if (!button || !enabled(button)) return; - const target = root.querySelector(`#${CSS.escape(button.getAttribute("aria-controls"))}`); - if (!target) return; - const expanded = button.getAttribute("aria-expanded") !== "true"; - button.setAttribute("aria-expanded", String(expanded)); - target.hidden = !expanded; - root.emit("toggle", { - id: target.id, - expanded - }); - }); - const details = root.querySelector("details"); - on(details, "toggle", () => root.emit("toggle", { - id: details.id, - expanded: details.open - })); - return { - get open() { - return details?.open ?? false; - }, - set open(value) { - if (details) details.open = Boolean(value); - } - }; -} -function combobox(root, { on, signal }) { - const input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"); - if (!input || !list) return {}; - identify(root, list, "options"); - input.setAttribute("aria-controls", list.id); - let active = null, notifying = false; - const notify = () => { - notifying = true; - try { - nativeInput(input); - nativeInput(input, "change"); - } finally { - notifying = false; - } - }; - const options = () => all(list, "[role=\"option\"]").filter((node) => enabled(node) && !node.hidden && !node.closest("[role=\"group\"][hidden]")); - all(list, "[role=\"option\"]").forEach((option, index) => identify(root, option, `option-${index}`)); - const setActive = (option) => { - active = option; - all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); - if (option) { - input.setAttribute("aria-activedescendant", option.id); - option.scrollIntoView({ block: "nearest" }); - } else input.removeAttribute("aria-activedescendant"); - }; - const hide = () => { - list.hidden = true; - input.setAttribute("aria-expanded", "false"); - setActive(null); - }; - const filter = (query = input.value) => { - for (const option of all(list, "[role=\"option\"]")) if (enabled(option)) option.hidden = !option.textContent.toLocaleLowerCase().includes(query.toLocaleLowerCase()); - all(list, "[role=\"group\"]").forEach((group) => { - group.hidden = !all(group, "[role=\"option\"]").some((node) => enabled(node) && !node.hidden); - }); - const empty = root.querySelector(".combobox-empty"); - if (empty) { - empty.hidden = options().length !== 0; - empty.classList.toggle("combobox-empty-shown", !empty.hidden); - } - if (!options().includes(active)) setActive(null); - }; - const show = (allOptions = false) => { - if (!enabled(input) || input.readOnly) return; - filter(allOptions ? "" : input.value); - list.hidden = false; - input.setAttribute("aria-expanded", "true"); - place(input, list); - }; - const choose = (option) => { - if (!option || !enabled(option)) return; - input.value = option.dataset.value ?? option.textContent.trim(); - hide(); - notify(); - input.focus(); - }; - on(input, "input", () => { - if (!notifying) { - show(); - announce(root, `${options().length} options available.`); - } - }); - on(input, "keydown", (event) => { - if (event.key === "Tab") { - hide(); - return; - } - if (event.key === "Escape") { - if (!list.hidden) { - hide(); - event.stopPropagation(); - } else if (input.value) { - input.value = ""; - notify(); - event.stopPropagation(); - } - event.preventDefault(); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - hide(); - return; - } - if (["ArrowDown", "ArrowUp"].includes(event.key)) { - event.preventDefault(); - if (list.hidden) show(true); - if (event.altKey) return; - const items = options(), index = active ? items.indexOf(active) : event.key === "ArrowDown" ? -1 : 0; - if (items.length) setActive(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); - } else if (event.key === "Enter" && !list.hidden && active) { - event.preventDefault(); - choose(active); - } - }); - on(list, "pointerdown", (event) => { - if (event.target.closest("[role=\"option\"]")) event.preventDefault(); - }); - on(list, "click", (event) => choose(event.target.closest("[role=\"option\"]"))); - on(root.querySelector(".combobox-toggle"), "click", () => { - list.hidden ? show(true) : hide(); - input.focus(); - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!root.contains(event.target)) hide(); - }); - on(root, "focusout", () => queueMicrotask(() => { - if (!signal.aborted && !root.contains(root.ownerDocument.activeElement)) hide(); - })); - on(root.ownerDocument.defaultView, "resize", () => { - if (!list.hidden) place(input, list); - }); - on(root.ownerDocument, "scroll", (event) => { - if (!list.hidden && !list.contains(event.target)) place(input, list); - }, { capture: true }); - hide(); - return { - show, - hide, - get open() { - return !list.hidden; - }, - set open(value) { - value ? show() : hide(); - }, - get value() { - return input.value; - }, - set value(value) { - input.value = String(value ?? ""); - if (!list.hidden) filter(); - }, - cleanup: hide - }; -} -function menu(root, { on }) { - const trigger = root.querySelector("button[aria-haspopup=\"menu\"]"), main = root.querySelector("[role=\"menu\"]"); - if (!trigger || !main) return {}; - identify(root, main, "menu"); - trigger.setAttribute("aria-controls", main.id); - const lists = all(root, "[role=\"menu\"]"); - const items = (list) => all(list, "[role^=\"menuitem\"]").filter((item) => item.closest("[role=\"menu\"]") === list); - const controller = (list) => all(root, "[aria-controls]").find((node) => node.getAttribute("aria-controls") === list.id); - const closeList = (list) => { - list.hidden = true; - controller(list)?.setAttribute("aria-expanded", "false"); - }; - const hide = (focus = true) => { - lists.forEach(closeList); - if (focus) trigger.focus(); - }; - const showList = (list, button, last = false) => { - list.hidden = false; - button.setAttribute("aria-expanded", "true"); - place(button, list); - rove(items(list), last ? items(list).length - 1 : 0); - }; - const show = () => { - if (enabled(trigger)) showList(main, trigger); - }; - const submenu = (button) => button.hasAttribute("aria-haspopup") ? lists.find((list) => list.id === button.getAttribute("aria-controls")) : null; - const activate = (item) => { - if (!enabled(item)) return; - const child = submenu(item); - if (child) { - showList(child, item); - return; - } - if (item.getAttribute("role") === "menuitemcheckbox") item.setAttribute("aria-checked", String(item.getAttribute("aria-checked") !== "true")); - else if (item.getAttribute("role") === "menuitemradio") items(item.closest("[role=\"menu\"]")).filter((node) => node.getAttribute("role") === "menuitemradio").forEach((node) => node.setAttribute("aria-checked", String(node === item))); - else hide(); - root.emit("action", { - action: item.dataset.action ?? item.textContent.trim(), - checked: item.getAttribute("aria-checked") === "true" - }); - }; - on(trigger, "click", () => main.hidden ? show() : hide()); - on(trigger, "keydown", (event) => { - if (["ArrowDown", "ArrowUp"].includes(event.key) && enabled(trigger)) { - event.preventDefault(); - showList(main, trigger, event.key === "ArrowUp"); - } - }); - on(root, "click", (event) => { - const item = event.target.closest("[role^=\"menuitem\"]"); - if (item) activate(item); - }); - on(root, "keydown", (event) => { - const item = event.target.closest("[role^=\"menuitem\"]"); - if (!item) return; - const list = item.closest("[role=\"menu\"]"), options = items(list), index = options.indexOf(item), rtl = getComputedStyle(list).direction === "rtl"; - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - rove(options, keyIndex({ - key: event.key, - index, - length: options.length - })); - } else if (event.key === "Escape" || event.key === (rtl ? "ArrowRight" : "ArrowLeft") && list !== main) { - event.preventDefault(); - event.stopPropagation(); - if (list !== main) { - closeList(list); - controller(list)?.focus(); - } else hide(); - } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight") && submenu(item)) { - event.preventDefault(); - showList(submenu(item), item); - } else if (event.key === "Tab") hide(); - else if (event.key.length === 1 && /\S/.test(event.key)) { - const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(".menu-label") ?? node).textContent.trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); - if (found) { - event.preventDefault(); - rove(options, options.indexOf(found)); - } - } - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!root.contains(event.target)) hide(false); - }); - on(root.ownerDocument, "focusin", (event) => { - if (!root.contains(event.target)) hide(false); - }); - on(root.ownerDocument.defaultView, "resize", () => lists.filter((list) => !list.hidden).forEach((list) => place(controller(list), list))); - hide(false); - return { - show, - hide, - get open() { - return !main.hidden; - }, - set open(value) { - value ? show() : hide(false); - }, - cleanup() { - hide(false); - } - }; -} -//#endregion -export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/file-browser/runtime/chunks/navigation-CknoksQ5.js b/packages/ui/dist/copy/file-browser/runtime/chunks/navigation-CknoksQ5.js new file mode 100644 index 000000000..dfd1883e6 --- /dev/null +++ b/packages/ui/dist/copy/file-browser/runtime/chunks/navigation-CknoksQ5.js @@ -0,0 +1,376 @@ +import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/navigation.js +function tabs(root, { on }, listOverride) { + const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); + if (!list) return {}; + const items = () => all(list, "[role=\"tab\"]").filter(enabled); + const select = (id, focus = false) => { + const tab = items().find((item) => item.id === id); + if (!tab) throw new RangeError(`Unknown enabled tab: ${id}`); + all(list, "[role=\"tab\"]").forEach((item) => { + item.setAttribute("aria-selected", String(item === tab)); + item.tabIndex = item === tab ? 0 : -1; + }); + all(root, "[role=\"tabpanel\"]").filter((panel) => all(list, "[role=\"tab\"]").some((tab) => tab.getAttribute("aria-controls") === panel.id)).forEach((panel) => { + panel.hidden = panel.id !== tab.getAttribute("aria-controls"); + if (!panel.hidden && !panel.querySelector("a[href],button,input,select,textarea,[tabindex='0']")) panel.tabIndex = 0; + }); + if (focus) tab.focus(); + return tab; + }; + const activate = (tab) => { + select(tab.id); + root.emit("select", { + id: tab.id, + panelId: tab.getAttribute("aria-controls") + }); + }; + on(list, "click", (event) => { + const tab = event.target.closest("[role=\"tab\"]"); + if (tab && enabled(tab)) activate(tab); + }); + on(list, "keydown", (event) => { + const current = event.target.closest("[role=\"tab\"]"), options = items(); + if (!current) return; + const vertical = list.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(list).direction === "rtl"; + const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", previous = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; + let index = options.indexOf(current); + if (event.key === next) index++; + else if (event.key === previous) index--; + else if (event.key === "Home") index = 0; + else if (event.key === "End") index = options.length - 1; + else if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + activate(current); + return; + } else return; + event.preventDefault(); + const tab = rove(options, index); + if (root.getAttribute("activation") !== "manual") activate(tab); + }); + const initial = items().find((item) => item.getAttribute("aria-selected") === "true") ?? items()[0]; + if (initial) select(initial.id); + return { + select, + get selectedId() { + return list.querySelector("[aria-selected=\"true\"]")?.id ?? ""; + }, + set selectedId(id) { + select(id); + } + }; +} +function toolbar(root, { on }) { + const bar = root.querySelector("[role=\"toolbar\"]"); + if (!bar) return {}; + const controls = () => all(bar, "button,a[href],input,select").filter((node) => enabled(node) && visible(node) && !node.closest("[role=\"menu\"]")); + const initial = controls(); + rove(initial, Math.max(0, initial.findIndex((node) => node.tabIndex === 0)), false); + on(bar, "focusin", (event) => { + if (controls().includes(event.target)) rove(controls(), controls().indexOf(event.target), false); + }); + on(bar, "keydown", (event) => { + if (event.target.matches("input,select,textarea") || event.target.closest("[role=\"menu\"]")) return; + const items = controls(), index = items.indexOf(event.target); + const vertical = bar.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(bar).direction === "rtl"; + const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", prev = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; + if (![ + next, + prev, + "Home", + "End" + ].includes(event.key)) return; + event.preventDefault(); + rove(items, keyIndex({ + key: event.key, + index, + length: items.length, + next, + previous: prev + })); + }); + on(bar, "click", (event) => { + const button = event.target.closest("button[aria-pressed]"); + if (button && enabled(button)) { + button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + root.emit("action", { + action: button.dataset.action ?? button.textContent.trim(), + pressed: button.getAttribute("aria-pressed") === "true" + }); + } + }); + return {}; +} +function disclosure(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button[aria-controls][aria-expanded]"); + if (!button || !enabled(button)) return; + const target = root.querySelector(`#${CSS.escape(button.getAttribute("aria-controls"))}`); + if (!target) return; + const expanded = button.getAttribute("aria-expanded") !== "true"; + button.setAttribute("aria-expanded", String(expanded)); + target.hidden = !expanded; + root.emit("toggle", { + id: target.id, + expanded + }); + }); + const details = root.querySelector("details"); + on(details, "toggle", () => root.emit("toggle", { + id: details.id, + expanded: details.open + })); + return { + get open() { + return details?.open ?? false; + }, + set open(value) { + if (details) details.open = Boolean(value); + } + }; +} +function combobox(root, { on, signal }) { + const input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"); + if (!input || !list) return {}; + identify(root, list, "options"); + input.setAttribute("aria-controls", list.id); + let active = null, notifying = false; + const notify = () => { + notifying = true; + try { + nativeInput(input); + nativeInput(input, "change"); + } finally { + notifying = false; + } + }; + const options = () => all(list, "[role=\"option\"]").filter((node) => enabled(node) && !node.hidden && !node.closest("[role=\"group\"][hidden]")); + all(list, "[role=\"option\"]").forEach((option, index) => identify(root, option, `option-${index}`)); + const setActive = (option) => { + active = option; + all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); + if (option) { + input.setAttribute("aria-activedescendant", option.id); + option.scrollIntoView({ block: "nearest" }); + } else input.removeAttribute("aria-activedescendant"); + }; + const hide = () => { + list.hidden = true; + input.setAttribute("aria-expanded", "false"); + setActive(null); + }; + const filter = (query = input.value) => { + for (const option of all(list, "[role=\"option\"]")) if (enabled(option)) option.hidden = !option.textContent.toLocaleLowerCase().includes(query.toLocaleLowerCase()); + all(list, "[role=\"group\"]").forEach((group) => { + group.hidden = !all(group, "[role=\"option\"]").some((node) => enabled(node) && !node.hidden); + }); + const empty = root.querySelector(".combobox-empty"); + if (empty) { + empty.hidden = options().length !== 0; + empty.classList.toggle("combobox-empty-shown", !empty.hidden); + } + if (!options().includes(active)) setActive(null); + }; + const show = (allOptions = false) => { + if (!enabled(input) || input.readOnly) return; + filter(allOptions ? "" : input.value); + list.hidden = false; + input.setAttribute("aria-expanded", "true"); + place(input, list); + }; + const choose = (option) => { + if (!option || !enabled(option)) return; + input.value = option.dataset.value ?? option.textContent.trim(); + hide(); + notify(); + input.focus(); + }; + on(input, "input", () => { + if (!notifying) { + show(); + announce(root, `${options().length} options available.`); + } + }); + on(input, "keydown", (event) => { + if (event.key === "Tab") { + hide(); + return; + } + if (event.key === "Escape") { + if (!list.hidden) { + hide(); + event.stopPropagation(); + } else if (input.value) { + input.value = ""; + notify(); + event.stopPropagation(); + } + event.preventDefault(); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + hide(); + return; + } + if (["ArrowDown", "ArrowUp"].includes(event.key)) { + event.preventDefault(); + if (list.hidden) show(true); + if (event.altKey) return; + const items = options(), index = active ? items.indexOf(active) : event.key === "ArrowDown" ? -1 : 0; + if (items.length) setActive(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); + } else if (event.key === "Enter" && !list.hidden && active) { + event.preventDefault(); + choose(active); + } + }); + on(list, "pointerdown", (event) => { + if (event.target.closest("[role=\"option\"]")) event.preventDefault(); + }); + on(list, "click", (event) => choose(event.target.closest("[role=\"option\"]"))); + on(root.querySelector(".combobox-toggle"), "click", () => { + list.hidden ? show(true) : hide(); + input.focus(); + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!root.contains(event.target)) hide(); + }); + on(root, "focusout", () => queueMicrotask(() => { + if (!signal.aborted && !root.contains(root.ownerDocument.activeElement)) hide(); + })); + on(root.ownerDocument.defaultView, "resize", () => { + if (!list.hidden) place(input, list); + }); + on(root.ownerDocument, "scroll", (event) => { + if (!list.hidden && !list.contains(event.target)) place(input, list); + }, { capture: true }); + hide(); + return { + show, + hide, + get open() { + return !list.hidden; + }, + set open(value) { + value ? show() : hide(); + }, + get value() { + return input.value; + }, + set value(value) { + input.value = String(value ?? ""); + if (!list.hidden) filter(); + }, + cleanup: hide + }; +} +function menu(root, { on }) { + const trigger = root.querySelector("button[aria-haspopup=\"menu\"]"), main = root.querySelector("[role=\"menu\"]"); + if (!trigger || !main) return {}; + identify(root, main, "menu"); + trigger.setAttribute("aria-controls", main.id); + const lists = all(root, "[role=\"menu\"]"); + const items = (list) => all(list, "[role^=\"menuitem\"]").filter((item) => item.closest("[role=\"menu\"]") === list); + const controller = (list) => all(root, "[aria-controls]").find((node) => node.getAttribute("aria-controls") === list.id); + const closeList = (list) => { + list.hidden = true; + controller(list)?.setAttribute("aria-expanded", "false"); + }; + const hide = (focus = true) => { + lists.forEach(closeList); + if (focus) trigger.focus(); + }; + const showList = (list, button, last = false) => { + list.hidden = false; + button.setAttribute("aria-expanded", "true"); + place(button, list); + rove(items(list), last ? items(list).length - 1 : 0); + }; + const show = () => { + if (enabled(trigger)) showList(main, trigger); + }; + const submenu = (button) => button.hasAttribute("aria-haspopup") ? lists.find((list) => list.id === button.getAttribute("aria-controls")) : null; + const activate = (item) => { + if (!enabled(item)) return; + const child = submenu(item); + if (child) { + showList(child, item); + return; + } + if (item.getAttribute("role") === "menuitemcheckbox") item.setAttribute("aria-checked", String(item.getAttribute("aria-checked") !== "true")); + else if (item.getAttribute("role") === "menuitemradio") items(item.closest("[role=\"menu\"]")).filter((node) => node.getAttribute("role") === "menuitemradio").forEach((node) => node.setAttribute("aria-checked", String(node === item))); + else hide(); + root.emit("action", { + action: item.dataset.action ?? item.textContent.trim(), + checked: item.getAttribute("aria-checked") === "true" + }); + }; + on(trigger, "click", () => main.hidden ? show() : hide()); + on(trigger, "keydown", (event) => { + if (["ArrowDown", "ArrowUp"].includes(event.key) && enabled(trigger)) { + event.preventDefault(); + showList(main, trigger, event.key === "ArrowUp"); + } + }); + on(root, "click", (event) => { + const item = event.target.closest("[role^=\"menuitem\"]"); + if (item) activate(item); + }); + on(root, "keydown", (event) => { + const item = event.target.closest("[role^=\"menuitem\"]"); + if (!item) return; + const list = item.closest("[role=\"menu\"]"), options = items(list), index = options.indexOf(item), rtl = getComputedStyle(list).direction === "rtl"; + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + rove(options, keyIndex({ + key: event.key, + index, + length: options.length + })); + } else if (event.key === "Escape" || event.key === (rtl ? "ArrowRight" : "ArrowLeft") && list !== main) { + event.preventDefault(); + event.stopPropagation(); + if (list !== main) { + closeList(list); + controller(list)?.focus(); + } else hide(); + } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight") && submenu(item)) { + event.preventDefault(); + showList(submenu(item), item); + } else if (event.key === "Tab") hide(); + else if (event.key.length === 1 && /\S/.test(event.key)) { + const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(".menu-label") ?? node).textContent.trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); + if (found) { + event.preventDefault(); + rove(options, options.indexOf(found)); + } + } + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!root.contains(event.target)) hide(false); + }); + on(root.ownerDocument, "focusin", (event) => { + if (!root.contains(event.target)) hide(false); + }); + on(root.ownerDocument.defaultView, "resize", () => lists.filter((list) => !list.hidden).forEach((list) => place(controller(list), list))); + hide(false); + return { + show, + hide, + get open() { + return !main.hidden; + }, + set open(value) { + value ? show() : hide(false); + }, + cleanup() { + hide(false); + } + }; +} +export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/file-browser/runtime/components/file-browser.js b/packages/ui/dist/copy/file-browser/runtime/components/file-browser.js index 2c355a89a..697933727 100644 --- a/packages/ui/dist/copy/file-browser/runtime/components/file-browser.js +++ b/packages/ui/dist/copy/file-browser/runtime/components/file-browser.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as fileBrowser } from "../chunks/compositions-D57dCsBz.js"; -//#region .cache/ui-build/entries/components/file-browser.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as fileBrowser } from "../chunks/compositions-DWG4tv9E.js"; +// .cache/ui-build/entries/components/file-browser.js var J3w1FileBrowser = class extends J3w1Element { static componentId = "file-browser"; static version = "4.0.0"; - static implementationId = "sha256-XNnX1ARH1szUReH6kSeTR1njKOACxLiUhBCmo9iNz8s="; + static implementationId = "sha256-4K76FMxRutTXWd2WQZ21c23gbzw5z86V0UnvwDOrigI="; static connect = fileBrowser; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1FileBrowser }; diff --git a/packages/ui/dist/copy/file-browser/runtime/components/tree.js b/packages/ui/dist/copy/file-browser/runtime/components/tree.js index e0f6bd8da..d64ee41f2 100644 --- a/packages/ui/dist/copy/file-browser/runtime/components/tree.js +++ b/packages/ui/dist/copy/file-browser/runtime/components/tree.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { i as tree } from "../chunks/advanced-CqBF0dSb.js"; -//#region .cache/ui-build/entries/components/tree.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { i as tree } from "../chunks/advanced-BrFnVc0y.js"; +// .cache/ui-build/entries/components/tree.js var J3w1Tree = class extends J3w1Element { static componentId = "tree"; static version = "4.0.0"; - static implementationId = "sha256-8E6bGMMWEmhgjIAfuDs1+pxcabRicShQao3beIvcNBY="; + static implementationId = "sha256-4tyCeiJO1ktFeL6tRtS1nNUZhSguTNcVzLun9Gw4gX0="; static connect = tree; static upgradeProperties = [ "disabled", @@ -28,5 +28,4 @@ var J3w1Tree = class extends J3w1Element { }); } }; -//#endregion export { J3w1Tree }; diff --git a/packages/ui/dist/copy/file-browser/runtime/register/file-browser.js b/packages/ui/dist/copy/file-browser/runtime/register/file-browser.js index 6d8b76ed5..5cb8c5889 100644 --- a/packages/ui/dist/copy/file-browser/runtime/register/file-browser.js +++ b/packages/ui/dist/copy/file-browser/runtime/register/file-browser.js @@ -1,7 +1,6 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import "./tree.js"; import { J3w1FileBrowser } from "../components/file-browser.js"; -//#region .cache/ui-build/entries/register/file-browser.js +// .cache/ui-build/entries/register/file-browser.js var element = registerElement("j3w1-file-browser", J3w1FileBrowser); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/file-browser/runtime/register/tree.js b/packages/ui/dist/copy/file-browser/runtime/register/tree.js index 0ecee9bca..eb6e73696 100644 --- a/packages/ui/dist/copy/file-browser/runtime/register/tree.js +++ b/packages/ui/dist/copy/file-browser/runtime/register/tree.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Tree } from "../components/tree.js"; -//#region .cache/ui-build/entries/register/tree.js +// .cache/ui-build/entries/register/tree.js var element = registerElement("j3w1-tree", J3w1Tree); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/file-input/manifest.json b/packages/ui/dist/copy/file-input/manifest.json index f00cc841e..552440612 100644 --- a/packages/ui/dist/copy/file-input/manifest.json +++ b/packages/ui/dist/copy/file-input/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/file-input.md", "dependencies": [ "register/file-input.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/file-input.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/file-input.js": "sha256-b3BX2Mpd3hOdCnJZepq1gTZKBfvGMgxtEWnrAg8yfHA=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/file-input.js": "sha256-kE0QDQfY2i/MZLrABzvzfCatNUO8IQsU+q/AXBy6hW4=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/file-input.js": "sha256-ExE88VufliqZThHiVWLYTWVQgGqDWBCWbuRUBn+ZGV8=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/file-input.js": "sha256-IH4BuOvApw1/fBKt00ZvlyYSHfmgpV7+vme74RPPjdU=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-39WZRXEdIS4uIHh7bXmFulEjX4bGk2S3+7jZc7VyC/w=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/file-input/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/file-input/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/file-input/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/file-input/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/file-input/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/file-input/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/file-input/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/file-input/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/file-input/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/file-input/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/file-input/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/file-input/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/file-input/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/file-input/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/file-input/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/file-input/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/file-input/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/file-input/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/file-input/runtime/components/file-input.js b/packages/ui/dist/copy/file-input/runtime/components/file-input.js index e90ea78d1..bacbe4c84 100644 --- a/packages/ui/dist/copy/file-input/runtime/components/file-input.js +++ b/packages/ui/dist/copy/file-input/runtime/components/file-input.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { i as fileInput } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/file-input.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { i as fileInput } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/file-input.js var J3w1FileInput = class extends J3w1Element { static componentId = "file-input"; static version = "4.0.0"; - static implementationId = "sha256-DYtJ1M3W9zNvFy3MIif27+5jsw2JssfZ5mpXTXwGBCo="; + static implementationId = "sha256-iOWh+VU40OcnTtYqrIhx4VuoRrJFI3lImsaGfHaNJew="; static connect = fileInput; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -16,5 +16,4 @@ var J3w1FileInput = class extends J3w1Element { return this._api?.files; } }; -//#endregion export { J3w1FileInput }; diff --git a/packages/ui/dist/copy/file-input/runtime/register/file-input.js b/packages/ui/dist/copy/file-input/runtime/register/file-input.js index 33be9dd6d..789bb5f20 100644 --- a/packages/ui/dist/copy/file-input/runtime/register/file-input.js +++ b/packages/ui/dist/copy/file-input/runtime/register/file-input.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1FileInput } from "../components/file-input.js"; -//#region .cache/ui-build/entries/register/file-input.js +// .cache/ui-build/entries/register/file-input.js var element = registerElement("j3w1-file-input", J3w1FileInput); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/filterable-table/manifest.json b/packages/ui/dist/copy/filterable-table/manifest.json index 0e13f278e..a48631f10 100644 --- a/packages/ui/dist/copy/filterable-table/manifest.json +++ b/packages/ui/dist/copy/filterable-table/manifest.json @@ -5,23 +5,23 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/filterable-table.md", "dependencies": [ "register/filterable-table.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "register/search-field.js", "components/search-field.js", - "chunks/native-BjBt1sUh.js", + "chunks/native-D61761VL.js", "components/filterable-table.js", - "chunks/tables-Cjr1EIJz.js" + "chunks/tables-zo8ebTOo.js" ], "files": { - "runtime/register/filterable-table.js": "sha256-14GtCkn2rDEs/16Zp9P3ejF4+WJRKBEjPP8iHA/QieY=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/register/search-field.js": "sha256-oIExIQ80Xzt1d5Y8KclVl+lAi+cgOMhKMFNPBz8fEXY=", - "runtime/components/search-field.js": "sha256-HCnoLO1ZZvDEqeON+Ir7Q+XChuArNr/tJ7H+lnVTJPw=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", - "runtime/components/filterable-table.js": "sha256-xbo/MykYle7VwG4ArKqnOAwxD6bA5BruTf9Mi33CxnE=", - "runtime/chunks/tables-Cjr1EIJz.js": "sha256-K6BF6M6xNawgWdL+NIcBRZmY98j45o69tBI034Ks4Bg=", + "runtime/register/filterable-table.js": "sha256-lPgjDjZWOIpHRh1cQ/CLEze3gvrrHq2LenxoIZiYwoo=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/register/search-field.js": "sha256-6LYU8HU+rH1uC262cp+QTcMOL1fOJadTf2sVIOar7yw=", + "runtime/components/search-field.js": "sha256-DR2wccoQwBDsamOMrOnUSaYWdhk+1zRdrnB9VfaIthY=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", + "runtime/components/filterable-table.js": "sha256-WhFAB4Ycphp6+E956qxhLre3L3oejvNcC1NGSNJrqHo=", + "runtime/chunks/tables-zo8ebTOo.js": "sha256-+LRPZmFKPk0oe8q3HDlfXCXkloBbkRbiFHVHczc3GEs=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-yuQ4f52VMqzL7ZWwuc/Ln3tYKuwWDma8x9yxx29wwLg=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/filterable-table/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/filterable-table/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/filterable-table/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/filterable-table/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/filterable-table/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/filterable-table/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/filterable-table/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/filterable-table/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/filterable-table/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/filterable-table/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/filterable-table/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/filterable-table/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/filterable-table/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/filterable-table/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/filterable-table/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/filterable-table/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/filterable-table/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/filterable-table/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/pagination/runtime/chunks/tables-Cjr1EIJz.js b/packages/ui/dist/copy/filterable-table/runtime/chunks/tables-zo8ebTOo.js similarity index 98% rename from packages/ui/dist/copy/pagination/runtime/chunks/tables-Cjr1EIJz.js rename to packages/ui/dist/copy/filterable-table/runtime/chunks/tables-zo8ebTOo.js index f82aaf25e..56f7f3dc3 100644 --- a/packages/ui/dist/copy/pagination/runtime/chunks/tables-Cjr1EIJz.js +++ b/packages/ui/dist/copy/filterable-table/runtime/chunks/tables-zo8ebTOo.js @@ -1,5 +1,5 @@ -import { c as keyIndex, f as rove, i as all, o as enabled, s as identify } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/tables.js +import { c as keyIndex, f as rove, i as all, o as enabled, s as identify } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/tables.js function table(root, { on }) { const element = root.querySelector("table"), body = element?.tBodies[0]; if (!element || !body) return {}; @@ -213,5 +213,4 @@ function pagination(root, { on }) { } }; } -//#endregion export { table as n, pagination as t }; diff --git a/packages/ui/dist/copy/filterable-table/runtime/components/filterable-table.js b/packages/ui/dist/copy/filterable-table/runtime/components/filterable-table.js index 5eb0b2d55..2274cd992 100644 --- a/packages/ui/dist/copy/filterable-table/runtime/components/filterable-table.js +++ b/packages/ui/dist/copy/filterable-table/runtime/components/filterable-table.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as table } from "../chunks/tables-Cjr1EIJz.js"; -//#region .cache/ui-build/entries/components/filterable-table.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as table } from "../chunks/tables-zo8ebTOo.js"; +// .cache/ui-build/entries/components/filterable-table.js var J3w1FilterableTable = class extends J3w1Element { static componentId = "filterable-table"; static version = "4.0.0"; - static implementationId = "sha256-SJvvFZ+/THkuQJCx1F2i0vCQ2C54dLton+9ipWE3sS8="; + static implementationId = "sha256-n4lw+oO+89at2wpqrQKIjlpTrVj3erNy5+KxBS7zT/o="; static connect = table; static upgradeProperties = [ "disabled", @@ -32,5 +32,4 @@ var J3w1FilterableTable = class extends J3w1Element { }); } }; -//#endregion export { J3w1FilterableTable }; diff --git a/packages/ui/dist/copy/filterable-table/runtime/components/search-field.js b/packages/ui/dist/copy/filterable-table/runtime/components/search-field.js index 666ca6dde..89b2baea5 100644 --- a/packages/ui/dist/copy/filterable-table/runtime/components/search-field.js +++ b/packages/ui/dist/copy/filterable-table/runtime/components/search-field.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/search-field.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/search-field.js var J3w1SearchField = class extends J3w1Element { static componentId = "search-field"; static version = "4.0.0"; - static implementationId = "sha256-nopARV2ViNiuyBqGv6KjxLJ3uaaVqRJ3K7Mgtg/mS7Q="; + static implementationId = "sha256-tI6csnLzo3YwSslahWEtsgW+3pvLdmXr4NI4noiRcxA="; static connect = fields; static upgradeProperties = [ "disabled", @@ -27,5 +27,4 @@ var J3w1SearchField = class extends J3w1Element { return this._api.clear(...args); } }; -//#endregion export { J3w1SearchField }; diff --git a/packages/ui/dist/copy/filterable-table/runtime/register/filterable-table.js b/packages/ui/dist/copy/filterable-table/runtime/register/filterable-table.js index 25aeaaee0..4e5aba1ab 100644 --- a/packages/ui/dist/copy/filterable-table/runtime/register/filterable-table.js +++ b/packages/ui/dist/copy/filterable-table/runtime/register/filterable-table.js @@ -1,7 +1,6 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import "./search-field.js"; import { J3w1FilterableTable } from "../components/filterable-table.js"; -//#region .cache/ui-build/entries/register/filterable-table.js +// .cache/ui-build/entries/register/filterable-table.js var element = registerElement("j3w1-filterable-table", J3w1FilterableTable); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/filterable-table/runtime/register/search-field.js b/packages/ui/dist/copy/filterable-table/runtime/register/search-field.js index 169a29a47..d30d137f6 100644 --- a/packages/ui/dist/copy/filterable-table/runtime/register/search-field.js +++ b/packages/ui/dist/copy/filterable-table/runtime/register/search-field.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1SearchField } from "../components/search-field.js"; -//#region .cache/ui-build/entries/register/search-field.js +// .cache/ui-build/entries/register/search-field.js var element = registerElement("j3w1-search-field", J3w1SearchField); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/form-builder/manifest.json b/packages/ui/dist/copy/form-builder/manifest.json index 0332e6dfd..f620c62fd 100644 --- a/packages/ui/dist/copy/form-builder/manifest.json +++ b/packages/ui/dist/copy/form-builder/manifest.json @@ -5,21 +5,21 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/form-builder.md", "dependencies": [ "register/form-builder.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", - "chunks/form-builder-BvWZCBPR.js", - "chunks/form-builder-BRIaVVFY.js", - "chunks/form-workflow-BKRLylvq.js", - "chunks/markup-DeQ4bEMR.js" + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", + "chunks/form-builder-CkeTBQe-.js", + "chunks/form-builder-DbZUZMo1.js", + "chunks/form-workflow-B183Y5gc.js", + "chunks/markup-AopKpwOF.js" ], "files": { - "runtime/register/form-builder.js": "sha256-tU2ZvWo2T/MuPBB3TOjq1zh7tLWYnPh0JidHFW7mDgQ=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/chunks/form-builder-BvWZCBPR.js": "sha256-co6mxdcVOLnQNkM8uCfl8kI63k0MGZh/3Fc+rbLIZb0=", - "runtime/chunks/form-builder-BRIaVVFY.js": "sha256-Tp9FV5rv/ZMCey3CeQsnuBF2JLbIPx+fHgNluS3DeBE=", - "runtime/chunks/form-workflow-BKRLylvq.js": "sha256-LcDxqsGpnid91QErVgWLIaXtB5KQS8Uad6Q2shJ1Ohc=", - "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", + "runtime/register/form-builder.js": "sha256-oXBX37RV8hqaewR2lwDVwOl2j/msYQin6hRz9lX1Jx4=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/chunks/form-builder-CkeTBQe-.js": "sha256-iRHlKYYOhwufdLevaEyOgE67JBEu4RoXRoac4B2A21I=", + "runtime/chunks/form-builder-DbZUZMo1.js": "sha256-pSdb7sCB5w/BFrtZppLI60CobZa9ao5sqyQkvChry2k=", + "runtime/chunks/form-workflow-B183Y5gc.js": "sha256-wj41Umu7N2n0VIHJWCVtrmjCwuzB8U0k+mah4rAekQ8=", + "runtime/chunks/markup-AopKpwOF.js": "sha256-/Dn3cWEmlRQzeQAPVf+C0AooVb1pdIQeNeqd1fQVoPc=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-AvaSTsUjkZrvH982LEeySHgVpBYhI16Uh3XGc3F36g4=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/form-builder/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/form-builder/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/form-builder/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/form-builder/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/form-builder/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/form-builder/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/form-builder/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/form-builder/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/form-builder/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/form-builder/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/form-builder/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/form-builder/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-BvWZCBPR.js b/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-CkeTBQe-.js similarity index 82% rename from packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-BvWZCBPR.js rename to packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-CkeTBQe-.js index a14d0d676..d749d2eba 100644 --- a/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-BvWZCBPR.js +++ b/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-CkeTBQe-.js @@ -1,6 +1,6 @@ -import { t as J3w1Element } from "./element-Dovcr9Ky.js"; -import { t as mountBuilder } from "./form-builder-BRIaVVFY.js"; -//#region packages/ui/src/behaviors/form-builder.js +import { t as J3w1Element } from "./element-DcrNU9Wh.js"; +import { t as mountBuilder } from "./form-builder-DbZUZMo1.js"; +// packages/ui/src/behaviors/form-builder.js function formBuilder(root, { signal }) { const editor = root.querySelector("[data-builder]"); if (!editor) throw new Error("The form builder requires the complete maintained editor and preview markup"); @@ -17,12 +17,11 @@ function formBuilder(root, { signal }) { cleanup: api.destroy }; } -//#endregion -//#region .cache/ui-build/entries/components/form-builder.js +// .cache/ui-build/entries/components/form-builder.js var J3w1FormBuilder = class extends J3w1Element { static componentId = "form-builder"; static version = "4.0.0"; - static implementationId = "sha256-dFrLEZ4jQ0jq5jBzJdmUBQ8504+zDzvRQmhv59pmQs4="; + static implementationId = "sha256-FO3zSzWMChoC10L1NZoNUpgmEHttCO6FI00qTLTik28="; static connect = formBuilder; static upgradeProperties = [ "disabled", @@ -50,5 +49,4 @@ var J3w1FormBuilder = class extends J3w1Element { }); } }; -//#endregion export { J3w1FormBuilder as t }; diff --git a/packages/ui/dist/chunks/form-builder-BRIaVVFY.js b/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-DbZUZMo1.js similarity index 99% rename from packages/ui/dist/chunks/form-builder-BRIaVVFY.js rename to packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-DbZUZMo1.js index afa6bc088..b9f3ff528 100644 --- a/packages/ui/dist/chunks/form-builder-BRIaVVFY.js +++ b/packages/ui/dist/copy/form-builder/runtime/chunks/form-builder-DbZUZMo1.js @@ -1,5 +1,5 @@ -import { a as FORM_LIMITS, i as FIELD_TYPES, n as emptyValues, r as parseFormSchema, t as mountWorkflow } from "./form-workflow-BKRLylvq.js"; -//#region scripts/lib/form-builder.mjs +import { a as FORM_LIMITS, i as FIELD_TYPES, n as emptyValues, r as parseFormSchema, t as mountWorkflow } from "./form-workflow-B183Y5gc.js"; +// scripts/lib/form-builder.mjs var createBuilder = (theme) => ({ definition: { schemaVersion: 1, @@ -71,8 +71,7 @@ var identity_default = { profile: "default", sourceDigest: "sha256-gSQ1VcVNkjVKCkTGXt6fbWGqvDCJTpGQsFjWGbriWi0=" }; -//#endregion -//#region packages/ui/src/internal/form-builder.js +// packages/ui/src/internal/form-builder.js var templates = { schemaVersion: 1, version: "4.0.0", @@ -248,5 +247,4 @@ var mountBuilder = (root, { signal } = {}) => { } }; }; -//#endregion export { mountBuilder as t }; diff --git a/packages/ui/dist/copy/form-builder/runtime/chunks/form-workflow-BKRLylvq.js b/packages/ui/dist/copy/form-builder/runtime/chunks/form-workflow-B183Y5gc.js similarity index 99% rename from packages/ui/dist/copy/form-builder/runtime/chunks/form-workflow-BKRLylvq.js rename to packages/ui/dist/copy/form-builder/runtime/chunks/form-workflow-B183Y5gc.js index 6ef25ba0b..185b472b6 100644 --- a/packages/ui/dist/copy/form-builder/runtime/chunks/form-workflow-BKRLylvq.js +++ b/packages/ui/dist/copy/form-builder/runtime/chunks/form-workflow-B183Y5gc.js @@ -1,5 +1,5 @@ -import { a as setAttribute, i as removeAttribute, n as hasClass, o as walkMarkup, r as namespaceMarkup } from "./markup-DeQ4bEMR.js"; -//#region \0rolldown/runtime.js +import { a as setAttribute, i as removeAttribute, n as hasClass, o as walkMarkup, r as namespaceMarkup } from "./markup-AopKpwOF.js"; +// \0rolldown/runtime.js var __defProp = Object.defineProperty; var __exportAll = (all, no_symbols) => { let target = {}; @@ -10,8 +10,7 @@ var __exportAll = (all, no_symbols) => { if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" }); return target; }; -//#endregion -//#region node_modules/zod/v4/core/util.js +// node_modules/zod/v4/core/util.js var util_exports = /* @__PURE__ */ __exportAll({ BIGINT_FORMAT_RANGES: () => BIGINT_FORMAT_RANGES, CONSTANT_CATCH: () => CONSTANT_CATCH, @@ -81,6 +80,7 @@ var util_exports = /* @__PURE__ */ __exportAll({ required: () => required, safeExtend: () => safeExtend, shallowClone: () => shallowClone, + sizeCaps: () => sizeCaps, slugify: () => slugify, stringifyPrimitive: () => stringifyPrimitive, toZod: () => toZod, @@ -520,6 +520,17 @@ function prefixIssues(path, issues) { function unwrapMessage(message) { return typeof message === "string" ? message : message?.message; } +/** The leading size checks of `defChecks` that set an upper bound, each paired with it. */ +function sizeCaps(defChecks) { + const caps = []; + for (const ch of defChecks ?? []) { + const d = ch._zod.def; + if (!/_(length|size)$|_equals$/.test(d.check)) break; + const max = d.maximum ?? d.length ?? d.size; + if (max >= 0) caps.push([max, ch]); + } + return caps; +} function attachSchema(issues, start, inst) { var _a; for (let i = start; i < issues.length; i++) (_a = issues[i]).schema ?? (_a.schema = inst); @@ -654,6 +665,7 @@ function hide(inst, key, value) { return own(inst, key, value, false); } /** Adds members a table derives from the instance: each builds on first read and shadows as own data, and assignment shadows the same way, as when these were own properties. */ +/* @__NO_SIDE_EFFECTS__ */ function derived(computes, table) { for (const key in computes) { const compute = computes[key]; @@ -777,8 +789,7 @@ function constantCatch(value) { fn[CONSTANT_CATCH] = true; return fn; } -//#endregion -//#region node_modules/zod/v4/core/core.js +// node_modules/zod/v4/core/core.js var _a$1; /** A special constant with type `never` */ var NEVER = /*@__PURE__*/ Object.freeze({ status: "aborted" }); @@ -807,6 +818,7 @@ function newError(Definition) { } return new Definition(); } +/* @__NO_SIDE_EFFECTS__ */ function $constructor(name, initializer, proto, params) { const zodProto = {}; function Internals(def) { @@ -886,8 +898,7 @@ function config(newConfig) { if (newConfig) Object.assign(globalConfig, newConfig); return globalConfig; } -//#endregion -//#region node_modules/zod/v4/core/errors.js +// node_modules/zod/v4/core/errors.js function _getMessage() { const internals = this._zod; internals.message ?? (internals.message = JSON.stringify(internals.def, jsonStringifyReplacer, 2)); @@ -938,8 +949,8 @@ var initializer$1 = (inst, def) => { }); } }; -var $ZodError = $constructor("$ZodError", initializer$1); -var $ZodRealError = $constructor("$ZodError", initializer$1, void 0, { Parent: Error }); +var $ZodError = /* @__PURE__ */ $constructor("$ZodError", initializer$1); +var $ZodRealError = /* @__PURE__ */ $constructor("$ZodError", initializer$1, void 0, { Parent: Error }); /** Get-or-create `obj[key]` as an own data property. A path segment naming an inherited member * ("toString", "constructor") would otherwise read through to the prototype, and assigning * "__proto__" would hit the setter instead of creating a key. */ @@ -1095,8 +1106,7 @@ function prettifyError(error) { } return lines.join("\n"); } -//#endregion -//#region node_modules/zod/v4/core/parse.js +// node_modules/zod/v4/core/parse.js function finalizeParams(callee, params) { return { callee: params?.callee ?? callee, @@ -1310,8 +1320,7 @@ var _safeDecodeAsync = (_Err) => async (schema, value, _ctx) => { return _safeParseAsync(_Err)(schema, value, _ctx); }; var safeDecodeAsync$1 = /* @__PURE__*/ _safeDecodeAsync($ZodRealError); -//#endregion -//#region node_modules/zod/v4/core/regexes.js +// node_modules/zod/v4/core/regexes.js var regexes_exports = /* @__PURE__ */ __exportAll({ anyString: () => anyString, base64: () => base64$1, @@ -1499,8 +1508,7 @@ var sha384_base64url = /*@__PURE__*/ fixedBase64url(64); var sha512_hex = /^[0-9a-fA-F]{128}$/; var sha512_base64 = /*@__PURE__*/ fixedBase64(86, "=="); var sha512_base64url = /*@__PURE__*/ fixedBase64url(86); -//#endregion -//#region node_modules/zod/v4/core/checks.js +// node_modules/zod/v4/core/checks.js var $ZodCheck = /*@__PURE__*/ $constructor("$ZodCheck", (inst, def) => { var _a; inst._zod ?? (inst._zod = {}); @@ -1947,8 +1955,7 @@ var $ZodCheckOverwrite = /*@__PURE__*/ $constructor("$ZodCheckOverwrite", (inst, payload.value = def.tx(payload.value); }; }); -//#endregion -//#region node_modules/zod/v4/core/doc.js +// node_modules/zod/v4/core/doc.js var Doc = class { constructor(args = [], closed = {}) { this.content = []; @@ -1981,15 +1988,13 @@ var Doc = class { return new F(...Object.keys(this.closed), `return function (${this.args.join(", ")}) {\n${content.join("\n")}\n};`)(...Object.values(this.closed)); } }; -//#endregion -//#region node_modules/zod/v4/core/versions.js +// node_modules/zod/v4/core/versions.js var version = { major: 4, minor: 6, - patch: 5 + patch: 7 }; -//#endregion -//#region node_modules/zod/v4/core/schemas.js +// node_modules/zod/v4/core/schemas.js var $ZodType = /*@__PURE__*/ $constructor("$ZodType", (inst, def) => { var _a; inst ?? (inst = {}); @@ -2680,6 +2685,28 @@ var $ZodDate = /*@__PURE__*/ $constructor("$ZodDate", (inst, def) => { return payload; }; }); +function capSize(inst, size) { + const caps = sizeCaps(inst._zod.def.checks); + if (!caps.length) return; + const cap = Math.min(...caps.map((c) => c[0])); + const parse = inst._zod.parse; + inst._zod.parse = (payload, ctx) => { + const n = size(payload.value); + if (n > cap && !ctx?.skipChecks && ctx?.direction !== "backward") { + for (const [max, ch] of sizeCaps(inst._zod.def.checks)) if (n > max && ch._zod.def.when(payload)) { + const start = payload.issues.length; + ch._zod.check(payload); + payload.issues[start].continue = false; + attachSchema(payload.issues, start, inst); + return payload; + } + } + return parse(payload, ctx); + }; +} +var arraySize = (input) => Array.isArray(input) ? input.length : -1; +var mapSize = (input) => input instanceof Map ? input.size : -1; +var setSize = (input) => input instanceof Set ? input.size : -1; function handleArrayResult(result, final, index) { if (result.issues.length) final.issues.push(...prefixIssues(index, result.issues)); final.value[index] = result.value; @@ -2717,6 +2744,7 @@ var $ZodArray = /*@__PURE__*/ $constructor("$ZodArray", (inst, def) => { if (proms.length) return Promise.all(proms).then(() => payload); return payload; }; + capSize(inst, arraySize); }); function handlePropertyResult(result, final, key, input, optin, optout) { const isPresent = key in input; @@ -2825,7 +2853,7 @@ var $ZodObject = /*@__PURE__*/ $constructor("$ZodObject", (inst, def) => { } return propValues; }); - const isObject$2 = isObject; + const isObject$1 = isObject; const catchall = def.catchall; let value; const memo = globalConfig.memoizer; @@ -2833,7 +2861,7 @@ var $ZodObject = /*@__PURE__*/ $constructor("$ZodObject", (inst, def) => { inst._zod.parse = (payload, ctx) => { value ?? (value = _normalized.value); const input = payload.value; - if (!isObject$2(input)) { + if (!isObject$1(input)) { payload.issues.push({ expected: "object", code: "invalid_type", @@ -2963,7 +2991,7 @@ var $ZodObjectJIT = /*@__PURE__*/ $constructor("$ZodObjectJIT", (inst, def) => { return doc.compile(); }; let fastpass; - const isObject$1 = isObject; + const isObject$2 = isObject; const jit = !globalConfig.jitless; const fastEnabled = jit && allowsEval.value; const catchall = def.catchall; @@ -2971,7 +2999,7 @@ var $ZodObjectJIT = /*@__PURE__*/ $constructor("$ZodObjectJIT", (inst, def) => { inst._zod.parse = (payload, ctx) => { value ?? (value = _normalized.value); const input = payload.value; - if (!isObject$1(input)) { + if (!isObject$2(input)) { payload.issues.push({ expected: "object", code: "invalid_type", @@ -3561,6 +3589,7 @@ var $ZodMap = /*@__PURE__*/ $constructor("$ZodMap", (inst, def) => { if (proms.length) return Promise.all(proms).then(() => payload); return payload; }; + capSize(inst, mapSize); }); function handleMapResult(keyResult, valueResult, final, key, input, inst, ctx) { if (keyResult.issues.length) { @@ -3620,6 +3649,7 @@ var $ZodSet = /*@__PURE__*/ $constructor("$ZodSet", (inst, def) => { if (proms.length) return Promise.all(proms).then(() => payload); return payload; }; + capSize(inst, setSize); }); function handleSetResult(result, final) { if (result.issues.length) final.issues.push(...result.issues); @@ -4142,8 +4172,7 @@ function handleRefineResult(result, payload, input, inst) { payload.issues.push(issue(_iss)); } } -//#endregion -//#region node_modules/zod/v4/core/memoizer.js +// node_modules/zod/v4/core/memoizer.js var $ZodCyclicError = class extends Error { constructor() { super(`Cannot parse a reference cycle that closes through a transform`); @@ -4404,8 +4433,7 @@ function isBackEdge(ctx, value) { const backEdges = ctx[STATE]?.backEdges; return backEdges !== void 0 && isRef(value) && backEdges.has(value); } -//#endregion -//#region node_modules/zod/v4/locales/ar.js +// node_modules/zod/v4/locales/ar.js var error$60 = () => { const Sizable = { string: { @@ -4511,8 +4539,7 @@ var error$60 = () => { function ar_default() { return { localeError: error$60() }; } -//#endregion -//#region node_modules/zod/v4/locales/az.js +// node_modules/zod/v4/locales/az.js var error$59 = () => { const Sizable = { string: { @@ -4618,8 +4645,7 @@ var error$59 = () => { function az_default() { return { localeError: error$59() }; } -//#endregion -//#region node_modules/zod/v4/locales/be.js +// node_modules/zod/v4/locales/be.js function getBelarusianPlural(count, one, few, many) { const absCount = Math.abs(count); const lastDigit = absCount % 10; @@ -4764,8 +4790,7 @@ var error$58 = () => { function be_default() { return { localeError: error$58() }; } -//#endregion -//#region node_modules/zod/v4/locales/bg.js +// node_modules/zod/v4/locales/bg.js var error$57 = () => { const Sizable = { string: { @@ -4881,8 +4906,7 @@ var error$57 = () => { function bg_default() { return { localeError: error$57() }; } -//#endregion -//#region node_modules/zod/v4/locales/bn.js +// node_modules/zod/v4/locales/bn.js var error$56 = () => { const Sizable = { string: { @@ -4988,8 +5012,7 @@ var error$56 = () => { function bn_default() { return { localeError: error$56() }; } -//#endregion -//#region node_modules/zod/v4/locales/ca.js +// node_modules/zod/v4/locales/ca.js var error$55 = () => { const Sizable = { string: { @@ -5095,8 +5118,7 @@ var error$55 = () => { function ca_default() { return { localeError: error$55() }; } -//#endregion -//#region node_modules/zod/v4/locales/ckb.js +// node_modules/zod/v4/locales/ckb.js var error$54 = () => { const Sizable = { string: { @@ -5232,8 +5254,7 @@ var error$54 = () => { function ckb_default() { return { localeError: error$54() }; } -//#endregion -//#region node_modules/zod/v4/locales/cs.js +// node_modules/zod/v4/locales/cs.js var error$53 = () => { const Sizable = { string: { @@ -5345,8 +5366,7 @@ var error$53 = () => { function cs_default() { return { localeError: error$53() }; } -//#endregion -//#region node_modules/zod/v4/locales/da.js +// node_modules/zod/v4/locales/da.js var error$52 = () => { const Sizable = { string: { @@ -5463,8 +5483,7 @@ var error$52 = () => { function da_default() { return { localeError: error$52() }; } -//#endregion -//#region node_modules/zod/v4/locales/de.js +// node_modules/zod/v4/locales/de.js var error$51 = () => { const Sizable = { string: { @@ -5574,8 +5593,7 @@ var error$51 = () => { function de_default() { return { localeError: error$51() }; } -//#endregion -//#region node_modules/zod/v4/locales/el.js +// node_modules/zod/v4/locales/el.js var error$50 = () => { const Sizable = { string: { @@ -5681,8 +5699,7 @@ var error$50 = () => { function el_default() { return { localeError: error$50() }; } -//#endregion -//#region node_modules/zod/v4/locales/en.js +// node_modules/zod/v4/locales/en.js var error$49 = () => { const Sizable = { string: { @@ -5789,8 +5806,7 @@ var error$49 = () => { function en_default() { return { localeError: error$49() }; } -//#endregion -//#region node_modules/zod/v4/locales/eo.js +// node_modules/zod/v4/locales/eo.js var error$48 = () => { const Sizable = { string: { @@ -5901,8 +5917,7 @@ var error$48 = () => { function eo_default() { return { localeError: error$48() }; } -//#endregion -//#region node_modules/zod/v4/locales/es.js +// node_modules/zod/v4/locales/es.js var error$47 = () => { const Sizable = { string: { @@ -6032,8 +6047,7 @@ var error$47 = () => { function es_default() { return { localeError: error$47() }; } -//#endregion -//#region node_modules/zod/v4/locales/fa.js +// node_modules/zod/v4/locales/fa.js var error$46 = () => { const Sizable = { string: { @@ -6143,8 +6157,7 @@ var error$46 = () => { function fa_default() { return { localeError: error$46() }; } -//#endregion -//#region node_modules/zod/v4/locales/fi.js +// node_modules/zod/v4/locales/fi.js var error$45 = () => { const Sizable = { string: { @@ -6266,8 +6279,7 @@ var error$45 = () => { function fi_default() { return { localeError: error$45() }; } -//#endregion -//#region node_modules/zod/v4/locales/fr.js +// node_modules/zod/v4/locales/fr.js var error$44 = () => { const Sizable = { string: { @@ -6391,8 +6403,7 @@ var error$44 = () => { function fr_default() { return { localeError: error$44() }; } -//#endregion -//#region node_modules/zod/v4/locales/fr-CA.js +// node_modules/zod/v4/locales/fr-CA.js var error$43 = () => { const Sizable = { string: { @@ -6498,8 +6509,7 @@ var error$43 = () => { function fr_CA_default() { return { localeError: error$43() }; } -//#endregion -//#region node_modules/zod/v4/locales/gu.js +// node_modules/zod/v4/locales/gu.js var error$42 = () => { const Sizable = { string: { @@ -6605,8 +6615,7 @@ var error$42 = () => { function gu_default() { return { localeError: error$42() }; } -//#endregion -//#region node_modules/zod/v4/locales/he.js +// node_modules/zod/v4/locales/he.js var error$41 = () => { const TypeNames = { string: { @@ -6938,8 +6947,7 @@ var error$41 = () => { function he_default() { return { localeError: error$41() }; } -//#endregion -//#region node_modules/zod/v4/locales/hi.js +// node_modules/zod/v4/locales/hi.js var error$40 = () => { const Sizable = { string: { @@ -7045,8 +7053,7 @@ var error$40 = () => { function hi_default() { return { localeError: error$40() }; } -//#endregion -//#region node_modules/zod/v4/locales/hr.js +// node_modules/zod/v4/locales/hr.js var error$39 = () => { const Sizable = { string: { @@ -7166,8 +7173,7 @@ var error$39 = () => { function hr_default() { return { localeError: error$39() }; } -//#endregion -//#region node_modules/zod/v4/locales/hu.js +// node_modules/zod/v4/locales/hu.js var error$38 = () => { const Sizable = { string: { @@ -7277,8 +7283,7 @@ var error$38 = () => { function hu_default() { return { localeError: error$38() }; } -//#endregion -//#region node_modules/zod/v4/locales/hy.js +// node_modules/zod/v4/locales/hy.js function getArmenianPlural(count, one, many) { return Math.abs(count) === 1 ? one : many; } @@ -7426,8 +7431,7 @@ var error$37 = () => { function hy_default() { return { localeError: error$37() }; } -//#endregion -//#region node_modules/zod/v4/locales/id.js +// node_modules/zod/v4/locales/id.js var error$36 = () => { const Sizable = { string: { @@ -7533,8 +7537,7 @@ var error$36 = () => { function id_default() { return { localeError: error$36() }; } -//#endregion -//#region node_modules/zod/v4/locales/is.js +// node_modules/zod/v4/locales/is.js var error$35 = () => { const Sizable = { string: { @@ -7644,8 +7647,7 @@ var error$35 = () => { function is_default() { return { localeError: error$35() }; } -//#endregion -//#region node_modules/zod/v4/locales/it.js +// node_modules/zod/v4/locales/it.js var error$34 = () => { const Sizable = { string: { @@ -7755,8 +7757,7 @@ var error$34 = () => { function it_default() { return { localeError: error$34() }; } -//#endregion -//#region node_modules/zod/v4/locales/ja.js +// node_modules/zod/v4/locales/ja.js var error$33 = () => { const Sizable = { string: { @@ -7866,8 +7867,7 @@ var error$33 = () => { function ja_default() { return { localeError: error$33() }; } -//#endregion -//#region node_modules/zod/v4/locales/ka.js +// node_modules/zod/v4/locales/ka.js var error$32 = () => { const Sizable = { string: { @@ -7980,8 +7980,7 @@ var error$32 = () => { function ka_default() { return { localeError: error$32() }; } -//#endregion -//#region node_modules/zod/v4/locales/km.js +// node_modules/zod/v4/locales/km.js var error$31 = () => { const Sizable = { string: { @@ -8092,14 +8091,12 @@ var error$31 = () => { function km_default() { return { localeError: error$31() }; } -//#endregion -//#region node_modules/zod/v4/locales/kh.js +// node_modules/zod/v4/locales/kh.js /** @deprecated Use `km` instead. */ function kh_default() { return km_default(); } -//#endregion -//#region node_modules/zod/v4/locales/kn.js +// node_modules/zod/v4/locales/kn.js var error$30 = () => { const Sizable = { string: { @@ -8205,8 +8202,7 @@ var error$30 = () => { function kn_default() { return { localeError: error$30() }; } -//#endregion -//#region node_modules/zod/v4/locales/ko.js +// node_modules/zod/v4/locales/ko.js var error$29 = () => { const Sizable = { string: { @@ -8316,8 +8312,7 @@ var error$29 = () => { function ko_default() { return { localeError: error$29() }; } -//#endregion -//#region node_modules/zod/v4/locales/lt.js +// node_modules/zod/v4/locales/lt.js var capitalizeFirstCharacter = (text) => { return text.charAt(0).toUpperCase() + text.slice(1); }; @@ -8501,8 +8496,7 @@ var error$28 = () => { function lt_default() { return { localeError: error$28() }; } -//#endregion -//#region node_modules/zod/v4/locales/mk.js +// node_modules/zod/v4/locales/mk.js var error$27 = () => { const Sizable = { string: { @@ -8612,8 +8606,7 @@ var error$27 = () => { function mk_default() { return { localeError: error$27() }; } -//#endregion -//#region node_modules/zod/v4/locales/ms.js +// node_modules/zod/v4/locales/ms.js var error$26 = () => { const Sizable = { string: { @@ -8722,8 +8715,7 @@ var error$26 = () => { function ms_default() { return { localeError: error$26() }; } -//#endregion -//#region node_modules/zod/v4/locales/ne.js +// node_modules/zod/v4/locales/ne.js var error$25 = () => { const Sizable = { string: { @@ -8829,8 +8821,7 @@ var error$25 = () => { function ne_default() { return { localeError: error$25() }; } -//#endregion -//#region node_modules/zod/v4/locales/nl.js +// node_modules/zod/v4/locales/nl.js var error$24 = () => { const Sizable = { string: { @@ -8941,8 +8932,7 @@ var error$24 = () => { function nl_default() { return { localeError: error$24() }; } -//#endregion -//#region node_modules/zod/v4/locales/nn.js +// node_modules/zod/v4/locales/nn.js var error$23 = () => { const Sizable = { string: { @@ -9052,8 +9042,7 @@ var error$23 = () => { function nn_default() { return { localeError: error$23() }; } -//#endregion -//#region node_modules/zod/v4/locales/no.js +// node_modules/zod/v4/locales/no.js var error$22 = () => { const Sizable = { string: { @@ -9163,8 +9152,7 @@ var error$22 = () => { function no_default() { return { localeError: error$22() }; } -//#endregion -//#region node_modules/zod/v4/locales/ota.js +// node_modules/zod/v4/locales/ota.js var error$21 = () => { const Sizable = { string: { @@ -9275,8 +9263,7 @@ var error$21 = () => { function ota_default() { return { localeError: error$21() }; } -//#endregion -//#region node_modules/zod/v4/locales/ps.js +// node_modules/zod/v4/locales/ps.js var error$20 = () => { const Sizable = { string: { @@ -9386,8 +9373,7 @@ var error$20 = () => { function ps_default() { return { localeError: error$20() }; } -//#endregion -//#region node_modules/zod/v4/locales/pl.js +// node_modules/zod/v4/locales/pl.js var error$19 = () => { const Sizable = { string: { @@ -9497,8 +9483,7 @@ var error$19 = () => { function pl_default() { return { localeError: error$19() }; } -//#endregion -//#region node_modules/zod/v4/locales/pt.js +// node_modules/zod/v4/locales/pt.js var error$18 = () => { const Sizable = { string: { unit: "caracteres" }, @@ -9690,8 +9675,7 @@ var error$18 = () => { function pt_default() { return { localeError: error$18() }; } -//#endregion -//#region node_modules/zod/v4/locales/pt-BR.js +// node_modules/zod/v4/locales/pt-BR.js var error$17 = () => { const Sizable = { string: { unit: "caracteres" }, @@ -9883,8 +9867,7 @@ var error$17 = () => { function pt_BR_default() { return { localeError: error$17() }; } -//#endregion -//#region node_modules/zod/v4/locales/ro.js +// node_modules/zod/v4/locales/ro.js var error$16 = () => { const Sizable = { string: { @@ -10003,8 +9986,7 @@ var error$16 = () => { function ro_default() { return { localeError: error$16() }; } -//#endregion -//#region node_modules/zod/v4/locales/ru.js +// node_modules/zod/v4/locales/ru.js function getRussianPlural(count, one, few, many) { const absCount = Math.abs(count); const lastDigit = absCount % 10; @@ -10149,8 +10131,7 @@ var error$15 = () => { function ru_default() { return { localeError: error$15() }; } -//#endregion -//#region node_modules/zod/v4/locales/sk.js +// node_modules/zod/v4/locales/sk.js var error$14 = () => { const Sizable = { string: { @@ -10262,8 +10243,7 @@ var error$14 = () => { function sk_default() { return { localeError: error$14() }; } -//#endregion -//#region node_modules/zod/v4/locales/sl.js +// node_modules/zod/v4/locales/sl.js var error$13 = () => { const Sizable = { string: { @@ -10373,8 +10353,7 @@ var error$13 = () => { function sl_default() { return { localeError: error$13() }; } -//#endregion -//#region node_modules/zod/v4/locales/sv.js +// node_modules/zod/v4/locales/sv.js var error$12 = () => { const Sizable = { string: { @@ -10484,8 +10463,7 @@ var error$12 = () => { function sv_default() { return { localeError: error$12() }; } -//#endregion -//#region node_modules/zod/v4/locales/ta.js +// node_modules/zod/v4/locales/ta.js var error$11 = () => { const Sizable = { string: { @@ -10596,8 +10574,7 @@ var error$11 = () => { function ta_default() { return { localeError: error$11() }; } -//#endregion -//#region node_modules/zod/v4/locales/tg.js +// node_modules/zod/v4/locales/tg.js var error$10 = () => { const Sizable = { string: { @@ -10710,8 +10687,7 @@ var error$10 = () => { function tg_default() { return { localeError: error$10() }; } -//#endregion -//#region node_modules/zod/v4/locales/th.js +// node_modules/zod/v4/locales/th.js var error$9 = () => { const Sizable = { string: { @@ -10822,8 +10798,7 @@ var error$9 = () => { function th_default() { return { localeError: error$9() }; } -//#endregion -//#region node_modules/zod/v4/locales/tk.js +// node_modules/zod/v4/locales/tk.js var error$8 = () => { const Sizable = { string: { @@ -10927,8 +10902,7 @@ var error$8 = () => { function tk_default() { return { localeError: error$8() }; } -//#endregion -//#region node_modules/zod/v4/locales/tr.js +// node_modules/zod/v4/locales/tr.js var error$7 = () => { const Sizable = { string: { @@ -11034,8 +11008,7 @@ var error$7 = () => { function tr_default() { return { localeError: error$7() }; } -//#endregion -//#region node_modules/zod/v4/locales/uk.js +// node_modules/zod/v4/locales/uk.js var error$6 = () => { const Sizable = { string: { @@ -11145,14 +11118,12 @@ var error$6 = () => { function uk_default() { return { localeError: error$6() }; } -//#endregion -//#region node_modules/zod/v4/locales/ua.js +// node_modules/zod/v4/locales/ua.js /** @deprecated Use `uk` instead. */ function ua_default() { return uk_default(); } -//#endregion -//#region node_modules/zod/v4/locales/ur.js +// node_modules/zod/v4/locales/ur.js var error$5 = () => { const Sizable = { string: { @@ -11263,8 +11234,7 @@ var error$5 = () => { function ur_default() { return { localeError: error$5() }; } -//#endregion -//#region node_modules/zod/v4/locales/uz.js +// node_modules/zod/v4/locales/uz.js var error$4 = () => { const Sizable = { string: { @@ -11374,8 +11344,7 @@ var error$4 = () => { function uz_default() { return { localeError: error$4() }; } -//#endregion -//#region node_modules/zod/v4/locales/vi.js +// node_modules/zod/v4/locales/vi.js var error$3 = () => { const Sizable = { string: { @@ -11485,8 +11454,7 @@ var error$3 = () => { function vi_default() { return { localeError: error$3() }; } -//#endregion -//#region node_modules/zod/v4/locales/zh-CN.js +// node_modules/zod/v4/locales/zh-CN.js var error$2 = () => { const Sizable = { string: { @@ -11597,8 +11565,7 @@ var error$2 = () => { function zh_CN_default() { return { localeError: error$2() }; } -//#endregion -//#region node_modules/zod/v4/locales/zh-TW.js +// node_modules/zod/v4/locales/zh-TW.js var error$1 = () => { const Sizable = { string: { @@ -11704,8 +11671,7 @@ var error$1 = () => { function zh_TW_default() { return { localeError: error$1() }; } -//#endregion -//#region node_modules/zod/v4/locales/yo.js +// node_modules/zod/v4/locales/yo.js var error = () => { const Sizable = { string: { @@ -11815,8 +11781,7 @@ var error = () => { function yo_default() { return { localeError: error() }; } -//#endregion -//#region node_modules/zod/v4/locales/index.js +// node_modules/zod/v4/locales/index.js var locales_exports = /* @__PURE__ */ __exportAll({ ar: () => ar_default, az: () => az_default, @@ -11882,8 +11847,7 @@ var locales_exports = /* @__PURE__ */ __exportAll({ zhCN: () => zh_CN_default, zhTW: () => zh_TW_default }); -//#endregion -//#region node_modules/zod/v4/core/registries.js +// node_modules/zod/v4/core/registries.js var _a; var $output = /*@__PURE__*/ Symbol("ZodOutput"); var $input = /*@__PURE__*/ Symbol("ZodInput"); @@ -11931,8 +11895,7 @@ function registry() { } (_a = globalThis).__zod_globalRegistry ?? (_a.__zod_globalRegistry = registry()); var globalRegistry = globalThis.__zod_globalRegistry; -//#endregion -//#region node_modules/zod/v4/core/compile.js +// node_modules/zod/v4/core/compile.js /** @internal Sentinel the compiled fast path returns when validation fails. */ var INVALID = Symbol.for("zod.compile.invalid"); var FALLBACK_FLAG = Symbol.for("zod.compile.fallback"); @@ -12917,9 +12880,13 @@ function generateNullableCheck(doc, ctx, schema, accessor, buildsValue = true) { doc.write(`}`); return outputVar; } +function generateSizeGate(doc, schema, size) { + for (const [max, check] of sizeCaps(schema._zod.def.checks)) doc.write(`if (${size} > ${numericOperand(max, check._zod.def.check)}) return INVALID;`); +} function generateArrayCheck(doc, ctx, schema, accessor, buildsValue = true) { const def = schema._zod.def; doc.write(`if (!Array.isArray(${accessor})) return INVALID;`); + generateSizeGate(doc, schema, `${accessor}.length`); const outputVar = buildsValue ? newVar(ctx) : null; const iVar = newVar(ctx); const elemVar = newVar(ctx); @@ -13256,6 +13223,7 @@ function literalPropertyKey(ctx, key) { function generateMapCheck(doc, ctx, schema, accessor) { const def = schema._zod.def; doc.write(`if (!(${accessor} instanceof Map)) return INVALID;`); + generateSizeGate(doc, schema, `${accessor}.size`); const outputVar = newVar(ctx); const kVar = newVar(ctx); const valVar = newVar(ctx); @@ -13272,6 +13240,7 @@ function generateMapCheck(doc, ctx, schema, accessor) { function generateSetCheck(doc, ctx, schema, accessor) { const def = schema._zod.def; doc.write(`if (!(${accessor} instanceof Set)) return INVALID;`); + generateSizeGate(doc, schema, `${accessor}.size`); const outputVar = newVar(ctx); const valVar = newVar(ctx); doc.write(`const ${outputVar} = new Set();`); @@ -13410,8 +13379,7 @@ function generateTransformCheck(doc, ctx, schema, accessor) { } return accessor; } -//#endregion -//#region node_modules/zod/v4/core/api.js +// node_modules/zod/v4/core/api.js function snapshotChecks(def) { if (def.checks) def.checks = [...def.checks]; return def; @@ -14488,8 +14456,7 @@ function _stringFormat(Class, format, fnOrRegex, _params = {}) { if (fnOrRegex instanceof RegExp) def.pattern = fnOrRegex; return new Class(def); } -//#endregion -//#region node_modules/zod/v4/core/to-json-schema.js +// node_modules/zod/v4/core/to-json-schema.js function assignProps(target, ...sources) { for (const source of sources) for (const key of Reflect.ownKeys(source)) if (Object.prototype.propertyIsEnumerable.call(source, key)) assignProp(target, key, source[key]); return target; @@ -14932,8 +14899,7 @@ var createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) = extractDefs(ctx, schema); return finalize(ctx, schema); }; -//#endregion -//#region node_modules/zod/v4/core/json-schema-processors.js +// node_modules/zod/v4/core/json-schema-processors.js var narrowMin = (agg, key, value) => { if (agg[key] === void 0 || value > agg[key]) agg[key] = value; }; @@ -15578,8 +15544,7 @@ function toJSONSchema(input, params) { extractDefs(ctx, input); return finalize(ctx, input); } -//#endregion -//#region node_modules/zod/v4/core/json-schema-generator.js +// node_modules/zod/v4/core/json-schema-generator.js /** * Legacy class-based interface for JSON Schema generation. * This class wraps the new functional implementation to provide backward compatibility. @@ -15669,11 +15634,9 @@ var JSONSchemaGenerator = class { return plainResult; } }; -//#endregion -//#region node_modules/zod/v4/core/json-schema.js +// node_modules/zod/v4/core/json-schema.js var json_schema_exports = /* @__PURE__ */ __exportAll({}); -//#endregion -//#region node_modules/zod/v4/core/index.js +// node_modules/zod/v4/core/index.js var core_exports = /* @__PURE__ */ __exportAll({ $ZodAny: () => $ZodAny, $ZodArray: () => $ZodArray, @@ -15988,8 +15951,7 @@ var core_exports = /* @__PURE__ */ __exportAll({ version: () => version, withParser: () => withParser }); -//#endregion -//#region node_modules/zod/v4/classic/checks.js +// node_modules/zod/v4/classic/checks.js var checks_exports = /* @__PURE__ */ __exportAll({ endsWith: () => _endsWith, gt: () => _gt, @@ -16022,8 +15984,7 @@ var checks_exports = /* @__PURE__ */ __exportAll({ trim: () => _trim, uppercase: () => _uppercase }); -//#endregion -//#region node_modules/zod/v4/classic/errors.js +// node_modules/zod/v4/classic/errors.js var _installedErrorProtos = /* @__PURE__ */ new WeakSet([Object.prototype, Error.prototype]); function _lazyMethod(proto, key, make) { Object.defineProperty(proto, key, { @@ -16073,8 +16034,7 @@ var initializer = (inst, issues) => { }; var ZodError = /*@__PURE__*/ $constructor("ZodError", initializer); var ZodRealError = /*@__PURE__*/ $constructor("ZodError", initializer, void 0, { Parent: Error }); -//#endregion -//#region node_modules/zod/v4/classic/parse.js +// node_modules/zod/v4/classic/parse.js var parse = /* @__PURE__ */ _parse(ZodRealError); var parseAsync = /* @__PURE__ */ _parseAsync(ZodRealError); var safeParse = /* @__PURE__ */ _safeParse(ZodRealError); @@ -16087,8 +16047,7 @@ var safeEncode = /* @__PURE__ */ _safeEncode(ZodRealError); var safeDecode = /* @__PURE__ */ _safeDecode(ZodRealError); var safeEncodeAsync = /* @__PURE__ */ _safeEncodeAsync(ZodRealError); var safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync(ZodRealError); -//#endregion -//#region node_modules/zod/v4/classic/schemas.js +// node_modules/zod/v4/classic/schemas.js var schemas_exports = /* @__PURE__ */ __exportAll({ ZodAny: () => ZodAny, ZodArray: () => ZodArray, @@ -17703,8 +17662,7 @@ function preprocess(fn, schema) { out: schema }); } -//#endregion -//#region node_modules/zod/v4/classic/compat.js +// node_modules/zod/v4/classic/compat.js /** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */ var ZodIssueCode = { invalid_type: "invalid_type", @@ -17730,8 +17688,7 @@ function getErrorMap() { /** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */ var ZodFirstPartyTypeKind; ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}); -//#endregion -//#region node_modules/zod/v4/classic/iso.js +// node_modules/zod/v4/classic/iso.js var iso_exports = /* @__PURE__ */ __exportAll({ ZodISODate: () => ZodISODate, ZodISODateTime: () => ZodISODateTime, @@ -17754,8 +17711,7 @@ function time(params) { function duration(params) { return /* @__PURE__ */ _isoDuration(ZodISODuration, params); } -//#endregion -//#region node_modules/zod/v4/classic/from-json-schema.js +// node_modules/zod/v4/classic/from-json-schema.js var z = { ...schemas_exports, ...checks_exports, @@ -18324,8 +18280,7 @@ function fromJSONSchema(schema, params) { }; return convertSchema(normalized, ctx); } -//#endregion -//#region node_modules/zod/v4/core/visit.js +// node_modules/zod/v4/core/visit.js var RESOLVING = Symbol("z.visit/resolving"); function visit(schema, fnOrHandlers) { const fn = typeof fnOrHandlers === "function" ? fnOrHandlers : (node, rewritten) => { @@ -18503,8 +18458,7 @@ function visit(schema, fnOrHandlers) { } return run(schema); } -//#endregion -//#region node_modules/zod/v4/classic/deep-partial.js +// node_modules/zod/v4/classic/deep-partial.js /** Returns a copy of the schema with every nested object's properties made optional. */ function deepPartial(schema) { return visit(schema, { @@ -18515,8 +18469,7 @@ function deepPartial(schema) { } }); } -//#endregion -//#region node_modules/zod/v4/classic/in-out.js +// node_modules/zod/v4/classic/in-out.js /** Appends a pipe's own checks to the side that replaces it, mirroring how `.check()` clones. */ function withChecks(side, checks) { if (!checks?.length) return side; @@ -18546,8 +18499,7 @@ function output(schema) { prefault: (s, rewritten) => rewritten ? s._zod.def.innerType : s }); } -//#endregion -//#region node_modules/zod/v4/classic/coerce.js +// node_modules/zod/v4/classic/coerce.js var coerce_exports = /* @__PURE__ */ __exportAll({ bigint: () => bigint, boolean: () => boolean, @@ -18570,8 +18522,7 @@ function bigint(params) { function date(params) { return /* @__PURE__ */ _coercedDate(ZodDate, params); } -//#endregion -//#region node_modules/zod/v4/classic/external.js +// node_modules/zod/v4/classic/external.js var external_exports = /* @__PURE__ */ __exportAll({ $brand: () => $brand, $input: () => $input, @@ -18832,8 +18783,7 @@ var external_exports = /* @__PURE__ */ __exportAll({ xid: () => xid, xor: () => xor }); -//#endregion -//#region schemas/form-schema.mjs +// schemas/form-schema.mjs var FIELD_TYPES = [ "text", "textarea", @@ -18889,8 +18839,7 @@ var formSchema = (z) => z.object({ path: ["fields"] }); }); -//#endregion -//#region scripts/lib/form-model.mjs +// scripts/lib/form-model.mjs var parseFormSchema = (text, theme) => { if (new TextEncoder().encode(text).length > FORM_LIMITS.bytes) throw new Error("Form schema exceeds the 64 KiB limit"); let data; @@ -18957,8 +18906,7 @@ var workflowTransition = (state, event, fields, validate = validateFields) => { }; throw new Error(`Unsupported workflow transition: ${state.stage} / ${event.type}`); }; -//#endregion -//#region node_modules/parse5/dist/common/unicode.js +// node_modules/parse5/dist/common/unicode.js var UNDEFINED_CODE_POINTS = /* @__PURE__ */ new Set([ 65534, 65535, @@ -19047,8 +18995,7 @@ function isControlCodePoint(cp) { function isUndefinedCodePoint(cp) { return cp >= 64976 && cp <= 65007 || UNDEFINED_CODE_POINTS.has(cp); } -//#endregion -//#region node_modules/parse5/dist/common/error-codes.js +// node_modules/parse5/dist/common/error-codes.js var ERR; (function(ERR) { ERR["controlCharacterInInputStream"] = "control-character-in-input-stream"; @@ -19112,8 +19059,7 @@ var ERR; ERR["nestedNoscriptInHead"] = "nested-noscript-in-head"; ERR["eofInElementThatCanContainOnlyText"] = "eof-in-element-that-can-contain-only-text"; })(ERR || (ERR = {})); -//#endregion -//#region node_modules/parse5/dist/tokenizer/preprocessor.js +// node_modules/parse5/dist/tokenizer/preprocessor.js var DEFAULT_BUFFER_WATERLINE = 65536; var Preprocessor = class { constructor(handler) { @@ -19263,8 +19209,7 @@ var Preprocessor = class { this.isEol = false; } }; -//#endregion -//#region node_modules/parse5/dist/common/token.js +// node_modules/parse5/dist/common/token.js var TokenType; (function(TokenType) { TokenType[TokenType["CHARACTER"] = 0] = "CHARACTER"; @@ -19281,8 +19226,7 @@ function getTokenAttr(token, attrName) { for (let i = token.attrs.length - 1; i >= 0; i--) if (token.attrs[i].name === attrName) return token.attrs[i].value; return null; } -//#endregion -//#region node_modules/parse5/node_modules/entities/dist/decode-codepoint.js +// node_modules/parse5/node_modules/entities/dist/decode-codepoint.js /** * C1 Unicode control character reference replacements (code points 128–159). * Index i gives the replacement for code point 128+i; 0 means "no replacement". @@ -19350,8 +19294,7 @@ function replaceCodePoint(codePoint) { function replaceCodePointXML(codePoint) { return isInvalidCodePoint(codePoint) ? 65533 : codePoint; } -//#endregion -//#region node_modules/parse5/node_modules/entities/dist/internal/decode-shared.js +// node_modules/parse5/node_modules/entities/dist/internal/decode-shared.js var BASE91_INVERSE = /* #__PURE__ */ (() => { const table = /* @__PURE__ */ new Uint8Array(127); let code = 0; @@ -19493,12 +19436,10 @@ function decodeTrieDict(input, resultLength, atomCount, dict1AtomCount, ngramCou } return out; } -//#endregion -//#region node_modules/parse5/node_modules/entities/dist/generated/decode-data-html.js +// node_modules/parse5/node_modules/entities/dist/generated/decode-data-html.js /** Packed HTML decode trie data. */ var htmlDecodeTree = /* #__PURE__ */ decodeTrieDict("!}.&u%}'&}*'~!6*)%&,~!J~!J~%L~y<~!R,~~%Lu~~#GD~~#|)1#%}^%}2%+#.##%##%}&%##%'#%##&%#%#'%#&#%#&#'#%%#&#%##%#)%''%&%#%#'%#%%#%%}%%%#%#&(23#%%#&-%0%('1#(##%#'##+%'*.:1}#%#6-+(%'%%#%%%}#L'2351&('%}&/N'(0(/*-%(%%}#'+&T%7.2}#&%&#%#36/5##%&%%#&#%%#))2%%##%&&'0~!#*+&'%1~!%).'3q?&%'1~!.##%6(~!+%%%(Gw'rT~!E#%#%&}*%}(%}9%}/%})%}*%}*%}?&}&%}3%}&*#%})%#%#)}#&#-#+*%E%%'%'#%}#*V##&##I}#&&##%&%#&&Qf%%))w/0+&%#(#.%-''''++++7}>%4'',##1,#%#&%##&#'##&#*#9)%&%}#*}%,#+P(%A&%#'&##wSD',9E00#y#@}(+}&%&>~!#~!X}#*}(&&}(&}(,%}%&#+&}#&}I%#%}%)#(},'%#*}4%%#%}(''}#/##(##),%-##%%)#&}(.}&%#&}%%}*&#%},&&}&%}#%*'#%})%}D&}&%}-&}6&#&}-,%}#%})-(~+`~,=?~I9'9%~!,#%})%})%}@%}?%}(~!?~#<~#pP~#BG~#=1#%K+~#?#~%;)~#A~#mF1~#A'~'X%'~#lR~#N~'N~#r~#m#-~#i'?%#'%~#B%##%,%#~#_%#0%~#]732~,w~2+#:&#%&'0%&>%}#>##F+)#%&&#(+_}4&}-%}(&}@&}O7Fdf0@+/v4}&WU##&/0#&'('B#%}.%}'+#%}#%%&#&%#%##+#&#)#6#'#.},%}c%},%#%##%&#&%#&~#>'*-.%##%##%}#%%}%'~#)D1}#%*&~#_%%'(~#S2%'.}#~#=##*'*-%}&'%'##&&~'E%.#&~#M4}%%##&'%#~#O1##%&#'+~#~#UA%-%##&~!C%~!-.9:~!1~!-^2/:a~!y,D*J#-5)/4~%23,~#G~!L1~!0X3`~!2+~!!0-~&E~!W~!o,>Y&]~%cZx_&~#O*9#A#'#+I'%#)~!0B*-5A+-((F&*M#)(-7-5+'-3a5Vi~!Y~!?+[)%3),ERHm~!+:D,VG.+)?fB%%*(%)'(#&80%1'8`K8?`+'Z#&O&'H5#*9)A%%5&3))0%39+.*7#()&&*=4@**L)<'_&*+..;(#*+)./&0#3)%')-8(4ixD(&.}%,('aI:,)%,k2231T)I'#/-W7,/'Q#.'Y24+h')37w+vu9i[~>g5uI~=RvdwEg;v/g;uk!!TTSx]@RT!U!#!@VBRUU!'UTe-d0c`e&gSdicedFcrdTaqb.kYcAohdYd@a3e+d}dMdtd.aJ#bqcK`dle/e.e'dwdPdodddjbEb}ogd^ofdpduc6j?l%d{drdqc)d7bacOdQ%T#Y)X.sR[yH>6Vyv3[xwLu>vo'!*.[yBacahoj>6Rew3[xqdZa#!a&#^(X-[yG>6Vyu3[xvg3sEr|g.u/Ri9db0T#^(Xa)!-[y;>6Vylg4wKs{JwNZt3@3r=c4Z([xlg;wKt!cpq's@v7A'*a(a+!-a#[y<3Dt?3Dt'>6Vym3[xmg9rxsNJwLZt4~?r?db1T#`-!(Xa,!0[yS>6Vz%NuQs.g4wKtnJwNZtS@3r>c4Z([y%g;wKtrdga8!a(!#&T*Y-Xa#!a06Vz43[y3JwNZtf@3s!Ju}!%Dti:pm3c_%X#tjB5pkd6q!r]u?voC'*-a.a2!0a&a+[yI3DtI3Ds~3DtH>6Vyw3[xx;:s#~<5pKJwNZtE@3r~d`a)!a2T#a.(!+U.X1[yT3Dt`3Dtv>6Vz&3[y&g9rxwzcxstPu.6Vz23[y1g3sEr}wkg{NuQRg{ci(U#5@b`~,cg#U(2WnH5wugcRh7dX#T(Y,a'Ta!!a,[yZ<]mj>6Vz,3[y+Pv#5ReZKu+=,%!H}7ABwkaS?Rh:BcW(X#<]mrj:ubv/ARekdg%!(!a.*Ta(Y.X1!#sP>Rl*Dt6[y>>6Vyo3Wf*jOvuumvuRgRJuq*!:96Re}3[xy~<5s%JwJZt1~Gs)c;&!#2sJkNuXvzq7rxu,Re8dka4!a8(aEZ+a@Y.X1Xa)[yd=Bs(3DtP>6Vz53[y4cX#X&Re:avRe9~<5s&JwJZtQ~Gs*i^rzvdRg+Jv{%!2sbB@bX}kdga,!Za?&^*T1/!a'Dt+[y6>6Vyf3Wf%g/u;s4hGu6?Rh-JvZ,!c%#&RoX54Rivj7uyvf8RgTKvZB%*!2sGh[y93Wf)coZ(T,6VyifluvRgC@95@B@bX~/hFu34cC#T,k/unq8w8Q5RkUklwQuzunq8w8Q5Rk8d/rJu?v8w9)-&!a0a;a&aIWejg3sEr/h1s23E~5c:Z&bX};kKv?w&unuVu5Rjc;>bs)#~@:Rh.=ay6Vyt3[xuNuPRi&NuPwpi#RoWh?vf8Ri%Jv]!%Ri:KvxD!.'2WeAjZu`q9rxu,Re7woeAg-unLq(qA_/*2Wg_g3u5q^9:4E}/jTrxrzv=Wkkd~0UX#^^Xa-a1a5T&a=U1a'*aEa]!a*aPaA-adok[y54Rn>;:p3~Dp5g9rpsFNvZqjg3uJp4~<5p0Pw;5qlJwNZt*@3p1Pw:5p/Ou!5p2JvG'!6Vye=Rl!9ARiq5E}Qg=ucRkBE|oJrJ_@Wk~@Wk{JrJ_@Wk|@WkyJrJ_@Wk}@WkzJvO_[y2g-vMRmiKuYC!)&>Ri;>Ri<@3RkNc](X#@9Rk=g5vuRmhKvDB!+'=]meg3u4Rmgd)#Y'Vz3CARmfd`a+!%T'!+#Ta1Ta6TaM-sTDt9[yA9sYd'%Y#s[[xpj:ueunaXRgEjRq,v-vuqdd2'`#6Rev<32@5>:2vyRgNj8w)v86Vyj3[xkg6ruwjcqsrPw;5r*Ku]D'Zt-@3r(~?r.i[vwv]dU1a--U#`a4(g/vsRhPOu!5RhLj:rmu9Wo!~@:wdh@g/vsRiTjXuvvNr}:RhBj^v(pyw8unRn]dz1UYa'a+^Y(!aETZalaRY.Ta?a4[yDJw1!#qLsW>6Vyrfzq-pLflpwRe|Js>%!Dt@3Dt&Jvy_[xs~HrnjMuwpsw'RecKu+D#'!t<~Grl~?rjg5u-x,gwp{ah!-(~@:Rg~Ou!5Rh'jXuvvNr}:Rh#cW#X/c;&!#2sLi[v7u7RgpJv)(!iLrxu,Re6j7v@s@5Se[e7d`aW!Za(a`T.a#!a3!&aDa-!9)Dt_=6s+3[x~~DR|h~DS6avhGun5RkZj3w)v-]mkKunB!&*]kb97R|icQ#%T'p-Rf8Rf=ct#%'(*!,p,Rf4p+Rf6Rf:Rf3Ds}KvGB)_6Vyk2sM=6Vyp;:pE~DrY~<5pBJwNZt8@3pCh=rt3rWPw:5pAJup_[xoNuPpF9c!#'45pD5ARn)d8#X'X*3@rU72s]h>v<RoUWeL>:Cbb|?JwPZtVg6ruRmzJvD'!6Vz(g/vmRh~Jvy_[y(g9voRgyx*cy(#2>Ri2B9b]~9kIw9u7rluJu3Rg]dI#a%UY'@=p%CAx.gQZ&RhwwygtRm{x5g_Z'+ABqR9Woa=Bp&dV#^*Xa'!&@o{g4v]Rk;Jv{!%Rk[wkkiA5RkiwwfUB=x,fUuqC&*!>RfTg8v0RfV~ARfSd;rJsAuAv9wR'ae+/aO!a@aza/a#[yQ@Wg!2Wemg3sEr0JvB_g>uvReWg2v+Re=KupB_+[y!2AbY~-~Hr2AJwD!(h<~El>h<~El?Kun@+_:9b`}Kg-v/Ri3g;vtwyk_9]k_d=&T#*U.6qh@Ab`|K9:H|CJv[!&3Dtex'fDwC%!Rf[9WlMd[(^X,!a%Z06Vz!@WgBg=v~Rgvg,QRe@awd,#Y+jTv|Q~EfWj]uNr|~FRfXdy#Y&^Ua%!aO.!(a)Ua;=!a@aKap!a-,a!Ta]a[rSa]p?[y82sK=Bq~;:p:~<5p8Pw:5p7d'#Y'Wf(;RnRi[u4w&RgJJvG'!6Vyh=)!&6Ri154s,KuGB_%@r68r:dJ|t`#X(9b6a3b%!/aKa/)!arwve^VyJ;:pR~DpTg3uJpS~<5pOPw;5qmPw:5pNOu!5pQJvG'!6Vyx=wkh'?Rh,x8gyt`w5D!&),(SgyccRgztJ@3pPB5p#d'(Y#<]mmifubw&RgoJvE&!82s^JvF&!8Rf,ADb]~;x=h'rNu]vK!,%'*0RnORh)4Rh*AqQg-vaRnNg;wHwkh'ba~4cE#Ta*x3gctyw@'!+%RnFRnD<4Rn@hFvK5RnCxWg[#`&a0Ua()`1Rm75Rg[c]%X#qi8Rg^NvdRj>BwzgZauwji7Rm6A4wgg]d1#&(*,.0a#Rm;RmRm?Rm@RmARmBe%#^^^Xaea?aC/b+(,!a+a#!a/!>a&Ta6Vy~g6urRf.x,hPrNav!%'RnqRo%Ro#Nu;q[Pw;5r+JwNZtM@3r)d'#Y'Weh;xChL#`&RnmRnoKu}>%(!Rne~Bs-;2wjcussJv+'!aYSO}6@B<5?ba~8LrNvj!.%*ROwungw~ng~:9;Ri^>wtnig;wHRnixDh@|(UZ.x1h@|)!#:2@=be}]?cl{{U#:5Abb}Jds#^YaF!a*b4a#a3aPa>&Tb!bH!*a_!Eau?/a&RjY<]gj>6Vz*;:pe~DrZg,QRj1JwNZtX@wihspcJvZ&!VyX9WmOJu|!|N2WmHJvh&!]ht~Bpbcn&T(!#RmQRmKCARhnKup=!)&Wf+:RhqNuPpf9c!#'45pd5AwghpARn(Ls@w!%,)!RmP@Wfe.a6!a:aO`aJDtL[y`@Wg#>6Vz12@wzoYRoZNuPRi!NuPRhzg=ucRi,@=b`{Yg=ucRi-ACJvB!&Sh[ebSh]ebi`wUuFRm4Jw2_[y0JvB!.>bU{0j9udv:Bb_{TJv`!&g/r|snj6v(us5d,#Y(56H}[978H}]Jw5!&g1rushJvB!+j;v{u5?zDhd}6}bj;v{u5?zDhe}6}ce*#`(^^^a[aea!=!a6a*aoXb1a.!aAbL!b>,b'aL!aV@Wf|2Wlg3[y/JwNZt^@3piPw:5pgJunZou3@rsJva&!Vy_gg5u-rqJvy'!@9RkQcH(T#=>Ri~@Ri}@2@@=aybb}XjWv0Q~EfEj3vLv;5@d##Y+jTv|vV~EfFj]uNpn~FRfGdgaK!Z2&!a8a-Tb({E!acTbM*!a(DtY[yYd'%Y#sl[y*hHvh>Re5x2c{Z}.j4uCvcawRiMd+#X+_x&d!},<5RkX;2Hzw@x,gavfB-!{CcF&T#Roe;RodwWbBg5urRgaKvHC*_6Vz+<4opieuew&Rmq@d]&Y)X,T#X0Rh}Ro5CE{A9b]{@;5x#eO{:g;urRi+KrNA!%(Ro3>Ro79;Ri_Ku@>{;&!x%gX|{KunA_+g5QRj/g3u5Rj#g>uERj%wio/xRhS&!,!#^1U}wba{8>>@=be}qC@:D5ba{7Ku+A&!}x?ba}t>>@=be}se(aA^^^Uat!b0#{pa+awUazbGa#aLb9bgaWac'a5TbS=Br!d1#`%scp_Jvl!#rT>Re0JvX&!VyN=H{Fcm#U&:pY=ReaJv2&!]h0=]nUJvG'!6Vy|=!|l=w^e1bp#&Re2Re3BDx7gH#T|f5H|eKuZ>!%(:qNAH{]Jv6!+3B2B9=b^{X<5x]z/@awRoTd+#Y(az]hFhCrm4d,#Y+jTv|Q~EfMj]uNr|~FRfOdCa!Xa9_X#@>@=be{#KuY>!+&4Ezyi[ugv&RjIdea+T)#UXa&T-T&a!Rh9auRmW=]kLg5vuRn+g3u4Rn-Ow6ARn,hHus5xNk?#UX(U~)/g8v0RkD~AwkkF?Ri.OuNBwkkA?Ri/d|a2`a*^UYa.!aBTZaTa'Xa;!(!2!-a#b2[yC>6Vyq3[xr2Wi?g1rusVh%s?DtF~<5rbJs;%!DtBfswKtCj[uvuSsEu3RgVx3o:u+wN'*Zt;@3rd~Grh~?rfg8w)Lq)qE&-a%!>bI|`jWv0vV~EfCjTv|vV~Ef@j]uNpn~FRfBcK#T']gWNu7x,k7q4ai(0!hHv8waiL2b`{QJv*_Ouv2qgjZa&!*UaA=2Wls3cH#T(@Ri|b~'#23s9h<~El.d'#Y&Dtxi^rzvdRl#d*#U%(o|B2s`hJwSaxRmDKv4B&!1:Rmdd5#`'Vx}to~Hq{x'f1v3(!BA5ba|bJv_&!Wfug1v]ReIdO+U/Y#&G}-8wze=Rh{g1v]ReHg/uQRf/by#)ibQwERl/cH#T(@Ri{cNu+vlax-!(#a0qa9aY?C9:9au@9Cb]}9cl#U*5;5KqRlR=c>Z,k#u3vWs@u2]krvgwyk^9]k^Jv3_@WfbAARkhJw2_[x|JvB_wkoIRoKwkoJRoLd'(Y#<]gm=<9Awwn;;Rn=c:Z'ARn<=Rn8Jw0!&>Rn:>Rn6cY#a7+!a&=978H{Dd_#{2^Y%_+qbbb{6g3sERhsbU{?dfa.,`a(XaRn7Jw0!&>Rn5>Rn9Lunw?&a2!,5ReGJwPZtK<7Rh+h<~El,Pv#5ReR@awwxjCg,ulRjDJv6&!]j!z?aQeeg>w=Shx'h-u(!%Ro.w~h.zPdNZ(X,Ya![x{;9ReY;wkgxRiF:x?ap#Y&RmUgA9:=b^}zKuh=a''!3awRk3c*'!#aHRk6c+Z&Rk5Rk4Jv)&!awRjSawd9*`#0?C2@EzMj8uuq@_+=ayb^|W~ARkEOuN]k@7dhzV^X/X&a-#zRzSb`zXcJzTT#2WkVKvDBzW!%FzY9;5bbzWjQrquJu3Jw3%!b`zU=ayb^zQd:#X(T-a!6Vyywxh}=b]{Jg=u1RiAdGp~qHtzv!w(wA+a+a;!,')~<5qeGzq9F{W=c##%s5au:5aU3CBE|;d4#X(D!a&6Vygx(b;#(=]ed?C2F{NaU@@=I|1OuNBc1Z+jTqIsBv=Wlc~Cw`fl2WlZ~AcTa%!Z+jTqIsBv=Wlb~Cw`fh2WlYk+uNqJsBv=WlSg,u3dca3#UXaMYa)TaB-=cM|7T#cB{/T#=ayaL.bo6!a#CbTa'T#Re{2Wlh2@G{yg6t~Ro_NvdRfticuRQRllJv3&!x&c|zs@Jw3!%RflwpfkRlpKuL;%(!Re<@G|C2GzdhIvuBwgjAg-u0RjAKQB%!(GzZ@G|5NuuRl7d='T+Y#Vy[gJvA!)@wma=]m1ifuaw&RmnLs@vT'!|/+[y,g:v>ReTJw1!#qX=x!eC{bLu+wT&)ZtZauq_~Graci&U#F|89:r_Lupvq!.)&2RlG8RfaC=x!eF{_h?rpWlmd&'!#X|&]k::xJey#`'T|+RlyARl9b[z[>RfZ:RlL:RfRwlg/ARl;9;RlxKv,A/!%7s69<74=BA5ba{-8Bde#`aRfk=ayb^}4~Ad1#`*@@=aybb{w2@>==KqRlT=c>Z,k#u3vWs@u2]kqReD2@G{42@G{5~DpM~<5rc=Bx6i>{RT#RnI@zCx]y]z:2Jv[!zr5Awyk]9]k]dD(Y+X#6Vz.g=wKtgwhaCwgmTWj2Lu,w%_+/[y-B;b^xeg3u3Rj-2@bX{*KrJRkdJwMZtc3Dtd@BcG#T'9bWxg2@2Fznd*#Y+;2x'c}wRn%:A5B;bZ~%KvhCa!a2!x>k7#Uxb@b{#xaRk7Jw0!)>wwhlShl}6>wwhmShm}6CJvB!.x'hhvj{!!5Bwkhhbaz}x'hivjz~!5Bwkhibaz|xEhTrNu,v-vpD!a%&/)a3a.,%Ro2t[CE{)@3re9b]{%wjo09:rgc:Z&Ro6=Ro89;Ri`dSaL'UYzxZb)7Rka3xRhT&!,!#^1U}vbaz{>>@=be}yC@:D5bazzKu+A&!}{?ba}y>>@=be}wxBh[t`u~vJvr!%a!a()a,a0a4RoC=]o;Ju(!%RoGRhdwjh`=]oAg>w#Ro?g5vuRo=NvdRl|Ku]C.!&;RoEJvB!%RoORoMBx'h[v+_?w~h`}~5?w~hd~!xKh]oiptu-utv.vp!#%&a30a@a'a+(a/aOp(o~p!RoDJu(!%RoHRhewjha=]oBNvdRl}g>w#Ro@g5vuRo>c[#X']ox7gL#TzuwjirRipcon;>z=h-MSh.Mwqczx'a7vj&!>Re4@=ResJt__NuPRi*NuPRi)j]uNr|~FRfzKrJ>_+@Wfy@Wf]2WocKrJRn1~?rOc:Z&Rn2=w=Rh=g3w*wwgGRgGcW(X#;Sg}M2Gzk@Jv`!&awRl=wsfGIz`dKZ*T'Y-:RhR7RhQg5u-p`j6v(us5d,#Y+~Awkia?RicOuNBwkibba}Ld6p~tyu_vbAa'a+!a/'a3aEa8a!>Sh,ebJv{!&Sh@ebSaReb9;SgwebNuPRi(NvdRl)NuPRi'hHu^(!a.3wkhZba~(x,h^u(A!&(SoCMRhb5Bz=h[eb?w~hb~6x,h_u(A!&(SoDMRhc5Bz=h]eb?w~hc~6e)aA1T#T,^^^c-bMb&blcPaP(a/!0!bA=b5c@a(!bfbrc#2afwmhARnjwchORnp2Wlf3DtsNvdRl-2@wpa<]m0bx(#:awRk2@Jw3!%RfhwpfgRlnKQB%!(G{V@G|'NuuRl6d='T+Y#VyUgw*wgj@g-u0Rj@Lu+wT&)ZtUauq]~GrGci&U#F|39:rELrNvj!.%*RhCwunfw~nf~:9;Ri]>wtnhg;wHRnhx3hDs@v~!/+'@Wfr@9RkSNu&Rlo=@<5GzoKs0@_+@Wl+@awRkmJuh!-3d(}pY#qWJvj!%Rm(:Jw3!%Rm,Rm*de&!1U-U#`)Re;@G|.@9Ri82@wjfvRlq=@<5GzpLvOvr!).&2RlF8Rf`C=x!eE{.Jw3_g2QRlkhLrpWlPde(!#U{s,UXa*Ta'[y'g:v>ReS;x0PZ&RnlRnn~HrKJw1}f!=x!eB|2w]aP(#Xa&a*Ta.Ua2a7=]iOd'#Y&Ro&WnWg;u.RiDg6vjRiBNvdRlzhNvj]nYJuW_2Wm3x)kFze{9d])!a.!,Y01!#&aC!a3RndC=ox~BrC@2b^{pg,rlse7x'ksuq!%Rm.E{xidw(wBRmGx9o+)X#wwo-So-}69:Rl4@xSf@a#XZ'X)X,Ta(/ARl8b[xc>RfY:RlI:RfQwlg.ARl:9;Rlwdn'#^XafaQa1X1TaHTa)@b[{zcZ#X'7RkwWg@Ou4ARn&x)kG#{,g7u/RkGdH'U#Y*Vz'Wm&CARm|bx#(A]gUbUzJj9Q~=d,#Y(56H}l978H{U7d,0#U*2>ABb_xZ978BbU{e~AJQ{g!978BbU{hxMh?ad{oUYZ.x1h?{l!#:2>@=be}F?JvS!&BG{d7BG}(Bde#`a1X,Ya@!a'P~=wxf@2bZ}I56B2@@=aybb}08@55B9;5bb}Rfg=ayb^}&OuNBKuLA!)a!P~=x#fD{f2@>==23ExY5@Dah89b^~689Jv)!~2b[~1Lv'w(%*!a#bX|aPrmawRe]keu7uhv-q6rxu,q`xTo]/a5aU!bNaDXbi!b-!ao!bRhG<7@C5vIbs)#?C2F|9jPv0w.vISh-MKvUaz(.!9ABbb|[5;5unwfh;9:4E|YjQsBt|vjx'hYq3!(?C2F|J:2kJv~vYrquJu3x4ib#T)2@SmZM?C2F|Bj:rmu9@xPhI(a*a#U#`a3-5Abb|L~@:RhK9:4E|0@52B5G|#C::aY?C2F|-:2!a)-g entry.type === EntryType.Element && entry.element === element); } }; -//#endregion -//#region node_modules/parse5/dist/tree-adapters/default.js +// node_modules/parse5/dist/tree-adapters/default.js var defaultTreeAdapter = { createDocument() { return { @@ -23147,8 +23081,7 @@ var defaultTreeAdapter = { }; } }; -//#endregion -//#region node_modules/parse5/dist/common/doctype.js +// node_modules/parse5/dist/common/doctype.js var VALID_DOCTYPE_NAME = "html"; var VALID_SYSTEM_ID = "about:legacy-compat"; var QUIRKS_MODE_SYSTEM_ID = "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"; @@ -23246,8 +23179,7 @@ function getDocumentMode(token) { } return DOCUMENT_MODE.NO_QUIRKS; } -//#endregion -//#region node_modules/parse5/dist/common/foreign-content.js +// node_modules/parse5/dist/common/foreign-content.js var MIME_TYPES = { TEXT_HTML: "text/html", APPLICATION_XML: "application/xhtml+xml" @@ -23503,8 +23435,7 @@ function isHtmlIntegrationPoint(tn, ns, attrs) { function isIntegrationPoint(tn, ns, attrs, foreignNS) { return (!foreignNS || foreignNS === NS.HTML) && isHtmlIntegrationPoint(tn, ns, attrs) || (!foreignNS || foreignNS === NS.MATHML) && isMathMLTextIntegrationPoint(tn, ns); } -//#endregion -//#region node_modules/parse5/dist/parser/index.js +// node_modules/parse5/dist/parser/index.js var HIDDEN_INPUT_TYPE = "hidden"; var AA_OUTER_LOOP_ITER = 8; var AA_INNER_LOOP_ITER = 3; @@ -25980,8 +25911,7 @@ function endTagInForeignContent(p, token) { } } } -//#endregion -//#region node_modules/parse5/node_modules/entities/dist/escape.js +// node_modules/parse5/node_modules/entities/dist/escape.js /** * Get the named reference for an XML special character or U+00A0. * @param char Code unit matched by one of the escape regexes. @@ -26028,8 +25958,7 @@ var textEscapeRegex = /[&<>\u{A0}]/gu; function escapeText(data) { return escapeWithRegex(textEscapeRegex, data); } -//#endregion -//#region node_modules/parse5/dist/serializer/index.js +// node_modules/parse5/dist/serializer/index.js var VOID_ELEMENTS = /* @__PURE__ */ new Set([ TAG_NAMES.AREA, TAG_NAMES.BASE, @@ -26140,8 +26069,7 @@ function serializeCommentNode(node, { treeAdapter }) { function serializeDocumentTypeNode(node, { treeAdapter }) { return ``; } -//#endregion -//#region node_modules/parse5/dist/index.js +// node_modules/parse5/dist/index.js function parseFragment(fragmentContext, html, options) { if (typeof fragmentContext === "string") { options = html; @@ -26152,8 +26080,7 @@ function parseFragment(fragmentContext, html, options) { parser.tokenizer.write(html, true); return parser.getFragment(); } -//#endregion -//#region scripts/lib/anchors.mjs +// scripts/lib/anchors.mjs var anchorFor = { verification: (id) => `v-${id}`, component: (id) => `c-${id}`, @@ -26178,8 +26105,7 @@ var anchorFor = { nonExample: (id) => `x-${id}`, fixture: (id) => `fx-${id.toLowerCase()}` }; -//#endregion -//#region scripts/lib/form-fields.mjs +// scripts/lib/form-fields.mjs var FIELD_COMPONENTS = { text: "text-field", textarea: "textarea", @@ -26311,8 +26237,7 @@ var readFieldValues = (root, fields, prefix) => Object.fromEntries(fields.map((f const value = field.type === "checkbox" ? input.checked : field.type === "radio" ? root.querySelector(`[name="${fieldControlId(prefix, field)}"]:checked`)?.value ?? "" : input.value; return [field.id, value]; })); -//#endregion -//#region packages/ui/src/internal/form-workflow.js +// packages/ui/src/internal/form-workflow.js var mountWorkflow = (root, { fields, templates, prefix, validate, signal }) => { const controller = new AbortController(); signal?.addEventListener("abort", () => controller.abort(), { once: true }); @@ -26425,5 +26350,4 @@ var mountWorkflow = (root, { fields, templates, prefix, validate, signal }) => { destroy: () => controller.abort() }; }; -//#endregion export { FORM_LIMITS as a, FIELD_TYPES as i, emptyValues as n, parseFormSchema as r, mountWorkflow as t }; diff --git a/packages/ui/dist/copy/command-palette/runtime/chunks/markup-DeQ4bEMR.js b/packages/ui/dist/copy/form-builder/runtime/chunks/markup-AopKpwOF.js similarity index 97% rename from packages/ui/dist/copy/command-palette/runtime/chunks/markup-DeQ4bEMR.js rename to packages/ui/dist/copy/form-builder/runtime/chunks/markup-AopKpwOF.js index 77bd9471d..bc1c52c0b 100644 --- a/packages/ui/dist/copy/command-palette/runtime/chunks/markup-DeQ4bEMR.js +++ b/packages/ui/dist/copy/form-builder/runtime/chunks/markup-AopKpwOF.js @@ -1,4 +1,4 @@ -//#region scripts/lib/markup.mjs +// scripts/lib/markup.mjs var IDREFS = /* @__PURE__ */ new Set([ "for", "form", @@ -50,5 +50,4 @@ var namespaceMarkup = (tree, decorate, { strict = true, renameNames = false } = else if (renameNames && attr.name === "name") attr.value = decorate(attr.value); }); }; -//#endregion export { setAttribute as a, removeAttribute as i, hasClass as n, walkMarkup as o, namespaceMarkup as r, IDREFS as t }; diff --git a/packages/ui/dist/copy/form-builder/runtime/register/form-builder.js b/packages/ui/dist/copy/form-builder/runtime/register/form-builder.js index c934349f3..2d2e2afb3 100644 --- a/packages/ui/dist/copy/form-builder/runtime/register/form-builder.js +++ b/packages/ui/dist/copy/form-builder/runtime/register/form-builder.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; -import { t as J3w1FormBuilder } from "../chunks/form-builder-BvWZCBPR.js"; -//#region .cache/ui-build/entries/register/form-builder.js +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; +import { t as J3w1FormBuilder } from "../chunks/form-builder-CkeTBQe-.js"; +// .cache/ui-build/entries/register/form-builder.js var element = registerElement("j3w1-form-builder", J3w1FormBuilder); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/i3-window-frame/manifest.json b/packages/ui/dist/copy/i3-window-frame/manifest.json index 78329417d..d477b8d50 100644 --- a/packages/ui/dist/copy/i3-window-frame/manifest.json +++ b/packages/ui/dist/copy/i3-window-frame/manifest.json @@ -5,19 +5,19 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/i3-window-frame.md", "dependencies": [ "register/i3-window-frame.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/i3-window-frame.js", - "chunks/compositions-D57dCsBz.js", - "chunks/navigation-BfNzDYZB.js" + "chunks/compositions-DWG4tv9E.js", + "chunks/navigation-CknoksQ5.js" ], "files": { - "runtime/register/i3-window-frame.js": "sha256-qJqHg9H/tx8mSRirpY3qYPpAbM/tk7akOF7Sb6yIBVw=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/i3-window-frame.js": "sha256-Xeo48w2qLhBiwCVHaA6whyxItZy/aAj1xHVCQHHnGhk=", - "runtime/chunks/compositions-D57dCsBz.js": "sha256-PEpI/vGgdD+LSznUd0iedSxxVE+5QxIO7BGKeQnCRjo=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", + "runtime/register/i3-window-frame.js": "sha256-Ov3rofs1avoZR0C4IqqkijLrojDAHlDuk7wor1rg70Q=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/i3-window-frame.js": "sha256-gKjEbi3JtUqHZR58RGIkZhx3LV31jTM0QacXjNxKLLE=", + "runtime/chunks/compositions-DWG4tv9E.js": "sha256-vV/UcQrj3UFpVXymFuH4t/h/T+7JqBeND9xuyVdCjqo=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-j6gn6V0mtTIbd0cJHobuNavfKnCi+dJ0Xg8IoZdHp/U=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/i3-window-frame/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/i3-window-frame/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/i3-window-frame/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/i3-window-frame/runtime/chunks/compositions-D57dCsBz.js b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/compositions-DWG4tv9E.js similarity index 91% rename from packages/ui/dist/copy/i3-window-frame/runtime/chunks/compositions-D57dCsBz.js rename to packages/ui/dist/copy/i3-window-frame/runtime/chunks/compositions-DWG4tv9E.js index f1da4562e..aa98d384a 100644 --- a/packages/ui/dist/copy/i3-window-frame/runtime/chunks/compositions-D57dCsBz.js +++ b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/compositions-DWG4tv9E.js @@ -1,6 +1,6 @@ -import { i as all, o as enabled } from "./choice-B7mo5Eq3.js"; -import { i as tabs } from "./navigation-BfNzDYZB.js"; -//#region packages/ui/src/behaviors/compositions.js +import { i as all, o as enabled } from "./choice-DqwWT5pJ.js"; +import { i as tabs } from "./navigation-CknoksQ5.js"; +// packages/ui/src/behaviors/compositions.js function fileBrowser(root, { on }) { const query = root.querySelector("[data-file-query]"), rows = all(root, "tr[data-file-id]"), status = root.querySelector("[data-file-status]"); let location = "all"; @@ -47,5 +47,4 @@ function windowFrame(root, context) { }); return {}; } -//#endregion export { fileBrowser as n, windowFrame as r, dashboard as t }; diff --git a/packages/ui/dist/copy/i3-window-frame/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/i3-window-frame/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/i3-window-frame/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/i3-window-frame/runtime/chunks/navigation-BfNzDYZB.js b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/navigation-BfNzDYZB.js deleted file mode 100644 index db2779553..000000000 --- a/packages/ui/dist/copy/i3-window-frame/runtime/chunks/navigation-BfNzDYZB.js +++ /dev/null @@ -1,377 +0,0 @@ -import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/navigation.js -function tabs(root, { on }, listOverride) { - const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); - if (!list) return {}; - const items = () => all(list, "[role=\"tab\"]").filter(enabled); - const select = (id, focus = false) => { - const tab = items().find((item) => item.id === id); - if (!tab) throw new RangeError(`Unknown enabled tab: ${id}`); - all(list, "[role=\"tab\"]").forEach((item) => { - item.setAttribute("aria-selected", String(item === tab)); - item.tabIndex = item === tab ? 0 : -1; - }); - all(root, "[role=\"tabpanel\"]").filter((panel) => all(list, "[role=\"tab\"]").some((tab) => tab.getAttribute("aria-controls") === panel.id)).forEach((panel) => { - panel.hidden = panel.id !== tab.getAttribute("aria-controls"); - if (!panel.hidden && !panel.querySelector("a[href],button,input,select,textarea,[tabindex='0']")) panel.tabIndex = 0; - }); - if (focus) tab.focus(); - return tab; - }; - const activate = (tab) => { - select(tab.id); - root.emit("select", { - id: tab.id, - panelId: tab.getAttribute("aria-controls") - }); - }; - on(list, "click", (event) => { - const tab = event.target.closest("[role=\"tab\"]"); - if (tab && enabled(tab)) activate(tab); - }); - on(list, "keydown", (event) => { - const current = event.target.closest("[role=\"tab\"]"), options = items(); - if (!current) return; - const vertical = list.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(list).direction === "rtl"; - const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", previous = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; - let index = options.indexOf(current); - if (event.key === next) index++; - else if (event.key === previous) index--; - else if (event.key === "Home") index = 0; - else if (event.key === "End") index = options.length - 1; - else if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - activate(current); - return; - } else return; - event.preventDefault(); - const tab = rove(options, index); - if (root.getAttribute("activation") !== "manual") activate(tab); - }); - const initial = items().find((item) => item.getAttribute("aria-selected") === "true") ?? items()[0]; - if (initial) select(initial.id); - return { - select, - get selectedId() { - return list.querySelector("[aria-selected=\"true\"]")?.id ?? ""; - }, - set selectedId(id) { - select(id); - } - }; -} -function toolbar(root, { on }) { - const bar = root.querySelector("[role=\"toolbar\"]"); - if (!bar) return {}; - const controls = () => all(bar, "button,a[href],input,select").filter((node) => enabled(node) && visible(node) && !node.closest("[role=\"menu\"]")); - const initial = controls(); - rove(initial, Math.max(0, initial.findIndex((node) => node.tabIndex === 0)), false); - on(bar, "focusin", (event) => { - if (controls().includes(event.target)) rove(controls(), controls().indexOf(event.target), false); - }); - on(bar, "keydown", (event) => { - if (event.target.matches("input,select,textarea") || event.target.closest("[role=\"menu\"]")) return; - const items = controls(), index = items.indexOf(event.target); - const vertical = bar.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(bar).direction === "rtl"; - const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", prev = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; - if (![ - next, - prev, - "Home", - "End" - ].includes(event.key)) return; - event.preventDefault(); - rove(items, keyIndex({ - key: event.key, - index, - length: items.length, - next, - previous: prev - })); - }); - on(bar, "click", (event) => { - const button = event.target.closest("button[aria-pressed]"); - if (button && enabled(button)) { - button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - root.emit("action", { - action: button.dataset.action ?? button.textContent.trim(), - pressed: button.getAttribute("aria-pressed") === "true" - }); - } - }); - return {}; -} -function disclosure(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button[aria-controls][aria-expanded]"); - if (!button || !enabled(button)) return; - const target = root.querySelector(`#${CSS.escape(button.getAttribute("aria-controls"))}`); - if (!target) return; - const expanded = button.getAttribute("aria-expanded") !== "true"; - button.setAttribute("aria-expanded", String(expanded)); - target.hidden = !expanded; - root.emit("toggle", { - id: target.id, - expanded - }); - }); - const details = root.querySelector("details"); - on(details, "toggle", () => root.emit("toggle", { - id: details.id, - expanded: details.open - })); - return { - get open() { - return details?.open ?? false; - }, - set open(value) { - if (details) details.open = Boolean(value); - } - }; -} -function combobox(root, { on, signal }) { - const input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"); - if (!input || !list) return {}; - identify(root, list, "options"); - input.setAttribute("aria-controls", list.id); - let active = null, notifying = false; - const notify = () => { - notifying = true; - try { - nativeInput(input); - nativeInput(input, "change"); - } finally { - notifying = false; - } - }; - const options = () => all(list, "[role=\"option\"]").filter((node) => enabled(node) && !node.hidden && !node.closest("[role=\"group\"][hidden]")); - all(list, "[role=\"option\"]").forEach((option, index) => identify(root, option, `option-${index}`)); - const setActive = (option) => { - active = option; - all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); - if (option) { - input.setAttribute("aria-activedescendant", option.id); - option.scrollIntoView({ block: "nearest" }); - } else input.removeAttribute("aria-activedescendant"); - }; - const hide = () => { - list.hidden = true; - input.setAttribute("aria-expanded", "false"); - setActive(null); - }; - const filter = (query = input.value) => { - for (const option of all(list, "[role=\"option\"]")) if (enabled(option)) option.hidden = !option.textContent.toLocaleLowerCase().includes(query.toLocaleLowerCase()); - all(list, "[role=\"group\"]").forEach((group) => { - group.hidden = !all(group, "[role=\"option\"]").some((node) => enabled(node) && !node.hidden); - }); - const empty = root.querySelector(".combobox-empty"); - if (empty) { - empty.hidden = options().length !== 0; - empty.classList.toggle("combobox-empty-shown", !empty.hidden); - } - if (!options().includes(active)) setActive(null); - }; - const show = (allOptions = false) => { - if (!enabled(input) || input.readOnly) return; - filter(allOptions ? "" : input.value); - list.hidden = false; - input.setAttribute("aria-expanded", "true"); - place(input, list); - }; - const choose = (option) => { - if (!option || !enabled(option)) return; - input.value = option.dataset.value ?? option.textContent.trim(); - hide(); - notify(); - input.focus(); - }; - on(input, "input", () => { - if (!notifying) { - show(); - announce(root, `${options().length} options available.`); - } - }); - on(input, "keydown", (event) => { - if (event.key === "Tab") { - hide(); - return; - } - if (event.key === "Escape") { - if (!list.hidden) { - hide(); - event.stopPropagation(); - } else if (input.value) { - input.value = ""; - notify(); - event.stopPropagation(); - } - event.preventDefault(); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - hide(); - return; - } - if (["ArrowDown", "ArrowUp"].includes(event.key)) { - event.preventDefault(); - if (list.hidden) show(true); - if (event.altKey) return; - const items = options(), index = active ? items.indexOf(active) : event.key === "ArrowDown" ? -1 : 0; - if (items.length) setActive(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); - } else if (event.key === "Enter" && !list.hidden && active) { - event.preventDefault(); - choose(active); - } - }); - on(list, "pointerdown", (event) => { - if (event.target.closest("[role=\"option\"]")) event.preventDefault(); - }); - on(list, "click", (event) => choose(event.target.closest("[role=\"option\"]"))); - on(root.querySelector(".combobox-toggle"), "click", () => { - list.hidden ? show(true) : hide(); - input.focus(); - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!root.contains(event.target)) hide(); - }); - on(root, "focusout", () => queueMicrotask(() => { - if (!signal.aborted && !root.contains(root.ownerDocument.activeElement)) hide(); - })); - on(root.ownerDocument.defaultView, "resize", () => { - if (!list.hidden) place(input, list); - }); - on(root.ownerDocument, "scroll", (event) => { - if (!list.hidden && !list.contains(event.target)) place(input, list); - }, { capture: true }); - hide(); - return { - show, - hide, - get open() { - return !list.hidden; - }, - set open(value) { - value ? show() : hide(); - }, - get value() { - return input.value; - }, - set value(value) { - input.value = String(value ?? ""); - if (!list.hidden) filter(); - }, - cleanup: hide - }; -} -function menu(root, { on }) { - const trigger = root.querySelector("button[aria-haspopup=\"menu\"]"), main = root.querySelector("[role=\"menu\"]"); - if (!trigger || !main) return {}; - identify(root, main, "menu"); - trigger.setAttribute("aria-controls", main.id); - const lists = all(root, "[role=\"menu\"]"); - const items = (list) => all(list, "[role^=\"menuitem\"]").filter((item) => item.closest("[role=\"menu\"]") === list); - const controller = (list) => all(root, "[aria-controls]").find((node) => node.getAttribute("aria-controls") === list.id); - const closeList = (list) => { - list.hidden = true; - controller(list)?.setAttribute("aria-expanded", "false"); - }; - const hide = (focus = true) => { - lists.forEach(closeList); - if (focus) trigger.focus(); - }; - const showList = (list, button, last = false) => { - list.hidden = false; - button.setAttribute("aria-expanded", "true"); - place(button, list); - rove(items(list), last ? items(list).length - 1 : 0); - }; - const show = () => { - if (enabled(trigger)) showList(main, trigger); - }; - const submenu = (button) => button.hasAttribute("aria-haspopup") ? lists.find((list) => list.id === button.getAttribute("aria-controls")) : null; - const activate = (item) => { - if (!enabled(item)) return; - const child = submenu(item); - if (child) { - showList(child, item); - return; - } - if (item.getAttribute("role") === "menuitemcheckbox") item.setAttribute("aria-checked", String(item.getAttribute("aria-checked") !== "true")); - else if (item.getAttribute("role") === "menuitemradio") items(item.closest("[role=\"menu\"]")).filter((node) => node.getAttribute("role") === "menuitemradio").forEach((node) => node.setAttribute("aria-checked", String(node === item))); - else hide(); - root.emit("action", { - action: item.dataset.action ?? item.textContent.trim(), - checked: item.getAttribute("aria-checked") === "true" - }); - }; - on(trigger, "click", () => main.hidden ? show() : hide()); - on(trigger, "keydown", (event) => { - if (["ArrowDown", "ArrowUp"].includes(event.key) && enabled(trigger)) { - event.preventDefault(); - showList(main, trigger, event.key === "ArrowUp"); - } - }); - on(root, "click", (event) => { - const item = event.target.closest("[role^=\"menuitem\"]"); - if (item) activate(item); - }); - on(root, "keydown", (event) => { - const item = event.target.closest("[role^=\"menuitem\"]"); - if (!item) return; - const list = item.closest("[role=\"menu\"]"), options = items(list), index = options.indexOf(item), rtl = getComputedStyle(list).direction === "rtl"; - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - rove(options, keyIndex({ - key: event.key, - index, - length: options.length - })); - } else if (event.key === "Escape" || event.key === (rtl ? "ArrowRight" : "ArrowLeft") && list !== main) { - event.preventDefault(); - event.stopPropagation(); - if (list !== main) { - closeList(list); - controller(list)?.focus(); - } else hide(); - } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight") && submenu(item)) { - event.preventDefault(); - showList(submenu(item), item); - } else if (event.key === "Tab") hide(); - else if (event.key.length === 1 && /\S/.test(event.key)) { - const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(".menu-label") ?? node).textContent.trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); - if (found) { - event.preventDefault(); - rove(options, options.indexOf(found)); - } - } - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!root.contains(event.target)) hide(false); - }); - on(root.ownerDocument, "focusin", (event) => { - if (!root.contains(event.target)) hide(false); - }); - on(root.ownerDocument.defaultView, "resize", () => lists.filter((list) => !list.hidden).forEach((list) => place(controller(list), list))); - hide(false); - return { - show, - hide, - get open() { - return !main.hidden; - }, - set open(value) { - value ? show() : hide(false); - }, - cleanup() { - hide(false); - } - }; -} -//#endregion -export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/i3-window-frame/runtime/chunks/navigation-CknoksQ5.js b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/navigation-CknoksQ5.js new file mode 100644 index 000000000..dfd1883e6 --- /dev/null +++ b/packages/ui/dist/copy/i3-window-frame/runtime/chunks/navigation-CknoksQ5.js @@ -0,0 +1,376 @@ +import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/navigation.js +function tabs(root, { on }, listOverride) { + const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); + if (!list) return {}; + const items = () => all(list, "[role=\"tab\"]").filter(enabled); + const select = (id, focus = false) => { + const tab = items().find((item) => item.id === id); + if (!tab) throw new RangeError(`Unknown enabled tab: ${id}`); + all(list, "[role=\"tab\"]").forEach((item) => { + item.setAttribute("aria-selected", String(item === tab)); + item.tabIndex = item === tab ? 0 : -1; + }); + all(root, "[role=\"tabpanel\"]").filter((panel) => all(list, "[role=\"tab\"]").some((tab) => tab.getAttribute("aria-controls") === panel.id)).forEach((panel) => { + panel.hidden = panel.id !== tab.getAttribute("aria-controls"); + if (!panel.hidden && !panel.querySelector("a[href],button,input,select,textarea,[tabindex='0']")) panel.tabIndex = 0; + }); + if (focus) tab.focus(); + return tab; + }; + const activate = (tab) => { + select(tab.id); + root.emit("select", { + id: tab.id, + panelId: tab.getAttribute("aria-controls") + }); + }; + on(list, "click", (event) => { + const tab = event.target.closest("[role=\"tab\"]"); + if (tab && enabled(tab)) activate(tab); + }); + on(list, "keydown", (event) => { + const current = event.target.closest("[role=\"tab\"]"), options = items(); + if (!current) return; + const vertical = list.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(list).direction === "rtl"; + const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", previous = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; + let index = options.indexOf(current); + if (event.key === next) index++; + else if (event.key === previous) index--; + else if (event.key === "Home") index = 0; + else if (event.key === "End") index = options.length - 1; + else if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + activate(current); + return; + } else return; + event.preventDefault(); + const tab = rove(options, index); + if (root.getAttribute("activation") !== "manual") activate(tab); + }); + const initial = items().find((item) => item.getAttribute("aria-selected") === "true") ?? items()[0]; + if (initial) select(initial.id); + return { + select, + get selectedId() { + return list.querySelector("[aria-selected=\"true\"]")?.id ?? ""; + }, + set selectedId(id) { + select(id); + } + }; +} +function toolbar(root, { on }) { + const bar = root.querySelector("[role=\"toolbar\"]"); + if (!bar) return {}; + const controls = () => all(bar, "button,a[href],input,select").filter((node) => enabled(node) && visible(node) && !node.closest("[role=\"menu\"]")); + const initial = controls(); + rove(initial, Math.max(0, initial.findIndex((node) => node.tabIndex === 0)), false); + on(bar, "focusin", (event) => { + if (controls().includes(event.target)) rove(controls(), controls().indexOf(event.target), false); + }); + on(bar, "keydown", (event) => { + if (event.target.matches("input,select,textarea") || event.target.closest("[role=\"menu\"]")) return; + const items = controls(), index = items.indexOf(event.target); + const vertical = bar.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(bar).direction === "rtl"; + const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", prev = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; + if (![ + next, + prev, + "Home", + "End" + ].includes(event.key)) return; + event.preventDefault(); + rove(items, keyIndex({ + key: event.key, + index, + length: items.length, + next, + previous: prev + })); + }); + on(bar, "click", (event) => { + const button = event.target.closest("button[aria-pressed]"); + if (button && enabled(button)) { + button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + root.emit("action", { + action: button.dataset.action ?? button.textContent.trim(), + pressed: button.getAttribute("aria-pressed") === "true" + }); + } + }); + return {}; +} +function disclosure(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button[aria-controls][aria-expanded]"); + if (!button || !enabled(button)) return; + const target = root.querySelector(`#${CSS.escape(button.getAttribute("aria-controls"))}`); + if (!target) return; + const expanded = button.getAttribute("aria-expanded") !== "true"; + button.setAttribute("aria-expanded", String(expanded)); + target.hidden = !expanded; + root.emit("toggle", { + id: target.id, + expanded + }); + }); + const details = root.querySelector("details"); + on(details, "toggle", () => root.emit("toggle", { + id: details.id, + expanded: details.open + })); + return { + get open() { + return details?.open ?? false; + }, + set open(value) { + if (details) details.open = Boolean(value); + } + }; +} +function combobox(root, { on, signal }) { + const input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"); + if (!input || !list) return {}; + identify(root, list, "options"); + input.setAttribute("aria-controls", list.id); + let active = null, notifying = false; + const notify = () => { + notifying = true; + try { + nativeInput(input); + nativeInput(input, "change"); + } finally { + notifying = false; + } + }; + const options = () => all(list, "[role=\"option\"]").filter((node) => enabled(node) && !node.hidden && !node.closest("[role=\"group\"][hidden]")); + all(list, "[role=\"option\"]").forEach((option, index) => identify(root, option, `option-${index}`)); + const setActive = (option) => { + active = option; + all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); + if (option) { + input.setAttribute("aria-activedescendant", option.id); + option.scrollIntoView({ block: "nearest" }); + } else input.removeAttribute("aria-activedescendant"); + }; + const hide = () => { + list.hidden = true; + input.setAttribute("aria-expanded", "false"); + setActive(null); + }; + const filter = (query = input.value) => { + for (const option of all(list, "[role=\"option\"]")) if (enabled(option)) option.hidden = !option.textContent.toLocaleLowerCase().includes(query.toLocaleLowerCase()); + all(list, "[role=\"group\"]").forEach((group) => { + group.hidden = !all(group, "[role=\"option\"]").some((node) => enabled(node) && !node.hidden); + }); + const empty = root.querySelector(".combobox-empty"); + if (empty) { + empty.hidden = options().length !== 0; + empty.classList.toggle("combobox-empty-shown", !empty.hidden); + } + if (!options().includes(active)) setActive(null); + }; + const show = (allOptions = false) => { + if (!enabled(input) || input.readOnly) return; + filter(allOptions ? "" : input.value); + list.hidden = false; + input.setAttribute("aria-expanded", "true"); + place(input, list); + }; + const choose = (option) => { + if (!option || !enabled(option)) return; + input.value = option.dataset.value ?? option.textContent.trim(); + hide(); + notify(); + input.focus(); + }; + on(input, "input", () => { + if (!notifying) { + show(); + announce(root, `${options().length} options available.`); + } + }); + on(input, "keydown", (event) => { + if (event.key === "Tab") { + hide(); + return; + } + if (event.key === "Escape") { + if (!list.hidden) { + hide(); + event.stopPropagation(); + } else if (input.value) { + input.value = ""; + notify(); + event.stopPropagation(); + } + event.preventDefault(); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + hide(); + return; + } + if (["ArrowDown", "ArrowUp"].includes(event.key)) { + event.preventDefault(); + if (list.hidden) show(true); + if (event.altKey) return; + const items = options(), index = active ? items.indexOf(active) : event.key === "ArrowDown" ? -1 : 0; + if (items.length) setActive(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); + } else if (event.key === "Enter" && !list.hidden && active) { + event.preventDefault(); + choose(active); + } + }); + on(list, "pointerdown", (event) => { + if (event.target.closest("[role=\"option\"]")) event.preventDefault(); + }); + on(list, "click", (event) => choose(event.target.closest("[role=\"option\"]"))); + on(root.querySelector(".combobox-toggle"), "click", () => { + list.hidden ? show(true) : hide(); + input.focus(); + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!root.contains(event.target)) hide(); + }); + on(root, "focusout", () => queueMicrotask(() => { + if (!signal.aborted && !root.contains(root.ownerDocument.activeElement)) hide(); + })); + on(root.ownerDocument.defaultView, "resize", () => { + if (!list.hidden) place(input, list); + }); + on(root.ownerDocument, "scroll", (event) => { + if (!list.hidden && !list.contains(event.target)) place(input, list); + }, { capture: true }); + hide(); + return { + show, + hide, + get open() { + return !list.hidden; + }, + set open(value) { + value ? show() : hide(); + }, + get value() { + return input.value; + }, + set value(value) { + input.value = String(value ?? ""); + if (!list.hidden) filter(); + }, + cleanup: hide + }; +} +function menu(root, { on }) { + const trigger = root.querySelector("button[aria-haspopup=\"menu\"]"), main = root.querySelector("[role=\"menu\"]"); + if (!trigger || !main) return {}; + identify(root, main, "menu"); + trigger.setAttribute("aria-controls", main.id); + const lists = all(root, "[role=\"menu\"]"); + const items = (list) => all(list, "[role^=\"menuitem\"]").filter((item) => item.closest("[role=\"menu\"]") === list); + const controller = (list) => all(root, "[aria-controls]").find((node) => node.getAttribute("aria-controls") === list.id); + const closeList = (list) => { + list.hidden = true; + controller(list)?.setAttribute("aria-expanded", "false"); + }; + const hide = (focus = true) => { + lists.forEach(closeList); + if (focus) trigger.focus(); + }; + const showList = (list, button, last = false) => { + list.hidden = false; + button.setAttribute("aria-expanded", "true"); + place(button, list); + rove(items(list), last ? items(list).length - 1 : 0); + }; + const show = () => { + if (enabled(trigger)) showList(main, trigger); + }; + const submenu = (button) => button.hasAttribute("aria-haspopup") ? lists.find((list) => list.id === button.getAttribute("aria-controls")) : null; + const activate = (item) => { + if (!enabled(item)) return; + const child = submenu(item); + if (child) { + showList(child, item); + return; + } + if (item.getAttribute("role") === "menuitemcheckbox") item.setAttribute("aria-checked", String(item.getAttribute("aria-checked") !== "true")); + else if (item.getAttribute("role") === "menuitemradio") items(item.closest("[role=\"menu\"]")).filter((node) => node.getAttribute("role") === "menuitemradio").forEach((node) => node.setAttribute("aria-checked", String(node === item))); + else hide(); + root.emit("action", { + action: item.dataset.action ?? item.textContent.trim(), + checked: item.getAttribute("aria-checked") === "true" + }); + }; + on(trigger, "click", () => main.hidden ? show() : hide()); + on(trigger, "keydown", (event) => { + if (["ArrowDown", "ArrowUp"].includes(event.key) && enabled(trigger)) { + event.preventDefault(); + showList(main, trigger, event.key === "ArrowUp"); + } + }); + on(root, "click", (event) => { + const item = event.target.closest("[role^=\"menuitem\"]"); + if (item) activate(item); + }); + on(root, "keydown", (event) => { + const item = event.target.closest("[role^=\"menuitem\"]"); + if (!item) return; + const list = item.closest("[role=\"menu\"]"), options = items(list), index = options.indexOf(item), rtl = getComputedStyle(list).direction === "rtl"; + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + rove(options, keyIndex({ + key: event.key, + index, + length: options.length + })); + } else if (event.key === "Escape" || event.key === (rtl ? "ArrowRight" : "ArrowLeft") && list !== main) { + event.preventDefault(); + event.stopPropagation(); + if (list !== main) { + closeList(list); + controller(list)?.focus(); + } else hide(); + } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight") && submenu(item)) { + event.preventDefault(); + showList(submenu(item), item); + } else if (event.key === "Tab") hide(); + else if (event.key.length === 1 && /\S/.test(event.key)) { + const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(".menu-label") ?? node).textContent.trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); + if (found) { + event.preventDefault(); + rove(options, options.indexOf(found)); + } + } + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!root.contains(event.target)) hide(false); + }); + on(root.ownerDocument, "focusin", (event) => { + if (!root.contains(event.target)) hide(false); + }); + on(root.ownerDocument.defaultView, "resize", () => lists.filter((list) => !list.hidden).forEach((list) => place(controller(list), list))); + hide(false); + return { + show, + hide, + get open() { + return !main.hidden; + }, + set open(value) { + value ? show() : hide(false); + }, + cleanup() { + hide(false); + } + }; +} +export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/i3-window-frame/runtime/components/i3-window-frame.js b/packages/ui/dist/copy/i3-window-frame/runtime/components/i3-window-frame.js index b22fc628b..e4aebb41e 100644 --- a/packages/ui/dist/copy/i3-window-frame/runtime/components/i3-window-frame.js +++ b/packages/ui/dist/copy/i3-window-frame/runtime/components/i3-window-frame.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as windowFrame } from "../chunks/compositions-D57dCsBz.js"; -//#region .cache/ui-build/entries/components/i3-window-frame.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as windowFrame } from "../chunks/compositions-DWG4tv9E.js"; +// .cache/ui-build/entries/components/i3-window-frame.js var J3w1I3WindowFrame = class extends J3w1Element { static componentId = "i3-window-frame"; static version = "4.0.0"; - static implementationId = "sha256-aoVPpcLCR1nIgTxPmR2un0VYei4XlfuvYsAk1YW7+mU="; + static implementationId = "sha256-jHRA5LlE/a4NeYo7D3jGN342NIG6HXu3MWIksnZGl0o="; static connect = windowFrame; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1I3WindowFrame }; diff --git a/packages/ui/dist/copy/i3-window-frame/runtime/register/i3-window-frame.js b/packages/ui/dist/copy/i3-window-frame/runtime/register/i3-window-frame.js index 75e3eb7d6..1de7561c2 100644 --- a/packages/ui/dist/copy/i3-window-frame/runtime/register/i3-window-frame.js +++ b/packages/ui/dist/copy/i3-window-frame/runtime/register/i3-window-frame.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1I3WindowFrame } from "../components/i3-window-frame.js"; -//#region .cache/ui-build/entries/register/i3-window-frame.js +// .cache/ui-build/entries/register/i3-window-frame.js var element = registerElement("j3w1-i3-window-frame", J3w1I3WindowFrame); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/icon-button/manifest.json b/packages/ui/dist/copy/icon-button/manifest.json index 8641d7b68..c8bb5474b 100644 --- a/packages/ui/dist/copy/icon-button/manifest.json +++ b/packages/ui/dist/copy/icon-button/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/icon-button.md", "dependencies": [ "register/icon-button.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/icon-button.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/icon-button.js": "sha256-L08i/ocUFPtCTSEsrOlL0bHzGs89QBIj/rBasLRJtLo=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/icon-button.js": "sha256-vf1OEF/kOZCVO/ZtfRZNwQ9lE6RvDSCB/Ra1MK1iFVI=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/icon-button.js": "sha256-Mw32ruY/czDFoyg4pH+EqKXUI/YsRFK4ZwwZotabWs4=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/icon-button.js": "sha256-wswYMnAITXd1cUjEIoNhQQb/Omx26cZEilDQ3SywHDk=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-il6XyTxz1/FNWyp/lAP2zeoQKrY/yezCXO7+BWH4SLU=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/icon-button/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/icon-button/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/icon-button/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/icon-button/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/icon-button/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/icon-button/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/icon-button/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/icon-button/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/icon-button/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/icon-button/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/icon-button/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/icon-button/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/icon-button/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/icon-button/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/icon-button/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/icon-button/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/icon-button/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/icon-button/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/icon-button/runtime/components/icon-button.js b/packages/ui/dist/copy/icon-button/runtime/components/icon-button.js index 1b617c987..8feab5d80 100644 --- a/packages/ui/dist/copy/icon-button/runtime/components/icon-button.js +++ b/packages/ui/dist/copy/icon-button/runtime/components/icon-button.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as actions } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/icon-button.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as actions } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/icon-button.js var J3w1IconButton = class extends J3w1Element { static componentId = "icon-button"; static version = "4.0.0"; - static implementationId = "sha256-6B32745m5D4H8EEVZL8U0DDC44RJN37XJIm7LWa43Gg="; + static implementationId = "sha256-2sCpHP7pmi2WBuPHJmS2gW9kHYHfcKQX9rMldNFRA8M="; static connect = actions; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...[ @@ -13,5 +13,4 @@ var J3w1IconButton = class extends J3w1Element { "tone" ]]; }; -//#endregion export { J3w1IconButton }; diff --git a/packages/ui/dist/copy/icon-button/runtime/register/icon-button.js b/packages/ui/dist/copy/icon-button/runtime/register/icon-button.js index ffdd0ac88..bc8b0ae7d 100644 --- a/packages/ui/dist/copy/icon-button/runtime/register/icon-button.js +++ b/packages/ui/dist/copy/icon-button/runtime/register/icon-button.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1IconButton } from "../components/icon-button.js"; -//#region .cache/ui-build/entries/register/icon-button.js +// .cache/ui-build/entries/register/icon-button.js var element = registerElement("j3w1-icon-button", J3w1IconButton); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/kbd/manifest.json b/packages/ui/dist/copy/kbd/manifest.json index 318915725..ea22f5a4d 100644 --- a/packages/ui/dist/copy/kbd/manifest.json +++ b/packages/ui/dist/copy/kbd/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/kbd.md", "dependencies": [ "register/kbd.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/kbd.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/kbd.js": "sha256-92LQ/OR8FLn8svoWLL7M3e0cPXvFcgItaJ0rUFKh7E4=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/kbd.js": "sha256-lHOj6iq9s2QEMIGqbh8RGMmnU1sbrGNw4+mbuKuvByQ=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/kbd.js": "sha256-T5QaA4+IeB2lompHOT73eTmRDgi/JZa13mu/uFS6g5k=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/kbd.js": "sha256-sREzCvdvlM8nxOV76TpFGUozKTATyfoHLHd9BRIvups=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-BOKm1Tw9r1muXSVI33rhSJD46PIEFVs790GKSMxz6a8=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/kbd/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/kbd/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/kbd/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/kbd/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/kbd/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/kbd/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/kbd/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/kbd/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/kbd/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/kbd/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/kbd/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/kbd/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/kbd/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/kbd/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/kbd/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/kbd/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/kbd/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/kbd/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/kbd/runtime/components/kbd.js b/packages/ui/dist/copy/kbd/runtime/components/kbd.js index 0556ef474..81775d00c 100644 --- a/packages/ui/dist/copy/kbd/runtime/components/kbd.js +++ b/packages/ui/dist/copy/kbd/runtime/components/kbd.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/kbd.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/kbd.js var J3w1Kbd = class extends J3w1Element { static componentId = "kbd"; static version = "4.0.0"; - static implementationId = "sha256-/6a09jGbevstnOqzIMGZWFLfMuQtcqnGZ7oWyH64Xdg="; + static implementationId = "sha256-hx5b1nufTNDjDCvzk6dWzvd0aXvqZApfBtz6slhMqWY="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Kbd }; diff --git a/packages/ui/dist/copy/kbd/runtime/register/kbd.js b/packages/ui/dist/copy/kbd/runtime/register/kbd.js index 6ae12a7fc..3b9a265db 100644 --- a/packages/ui/dist/copy/kbd/runtime/register/kbd.js +++ b/packages/ui/dist/copy/kbd/runtime/register/kbd.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Kbd } from "../components/kbd.js"; -//#region .cache/ui-build/entries/register/kbd.js +// .cache/ui-build/entries/register/kbd.js var element = registerElement("j3w1-kbd", J3w1Kbd); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/link/manifest.json b/packages/ui/dist/copy/link/manifest.json index 4a02632e0..84cc165dc 100644 --- a/packages/ui/dist/copy/link/manifest.json +++ b/packages/ui/dist/copy/link/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/link.md", "dependencies": [ "register/link.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/link.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/link.js": "sha256-U3xi1OrLtFVeA80lAjw3YJnW9ACONTzsce1B9Xf844w=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/link.js": "sha256-bR26HhC67XHGaYwnQAazew60MupqT70YRgV+2U5TNxA=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/link.js": "sha256-jwozmacnZdRn6lvmvgeeUqRw+j+qRnBfRC2vt9UgGbk=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/link.js": "sha256-k1UsDjyh7ID9N1QSWtczvBEYdMfs4xsybrRLTGFzYGQ=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-uxvP2GjnvVzGp+CHY0D7UPQ+7qXQiFem1DAnSc7jCyY=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/link/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/link/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/link/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/link/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/link/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/link/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/link/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/link/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/link/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/link/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/link/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/link/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/link/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/link/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/link/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/link/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/link/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/link/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/link/runtime/components/link.js b/packages/ui/dist/copy/link/runtime/components/link.js index 2356d4084..34afeeb1e 100644 --- a/packages/ui/dist/copy/link/runtime/components/link.js +++ b/packages/ui/dist/copy/link/runtime/components/link.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/link.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/link.js var J3w1Link = class extends J3w1Element { static componentId = "link"; static version = "4.0.0"; - static implementationId = "sha256-rEWDiPkjpyMkw7piXIpFnMc4x8xrVQVhLrBLQWgZXRM="; + static implementationId = "sha256-3rkQqxiNynw2Jw3SNY8V8khbmwWjkmKX6812xUp86hg="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Link }; diff --git a/packages/ui/dist/copy/link/runtime/register/link.js b/packages/ui/dist/copy/link/runtime/register/link.js index 669ae18ab..3713e5636 100644 --- a/packages/ui/dist/copy/link/runtime/register/link.js +++ b/packages/ui/dist/copy/link/runtime/register/link.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Link } from "../components/link.js"; -//#region .cache/ui-build/entries/register/link.js +// .cache/ui-build/entries/register/link.js var element = registerElement("j3w1-link", J3w1Link); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/list/manifest.json b/packages/ui/dist/copy/list/manifest.json index 89fc927ac..8e3a0d7d0 100644 --- a/packages/ui/dist/copy/list/manifest.json +++ b/packages/ui/dist/copy/list/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/list.md", "dependencies": [ "register/list.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/list.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/list.js": "sha256-f4HxPopmKcmXd3NOYv8arFYm1XmjhvpF0kbNynVYRUA=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/list.js": "sha256-X5HE772qpMx/n9b3NU6shv9zZWfmY9cjVn/IPAjFFMY=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/list.js": "sha256-a45MSP7U1eidIIzXWaMOiq9jf/+2F55E2LMAlxs0y14=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/list.js": "sha256-HjtEbhFT1/HcbIdaHdYeVWRI7h4AixKYxqdBxWVJwwk=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-rYecTkHR0B1N85CpEe58zzTavkIhRIQVzj50yKfdefA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/list/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/list/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/list/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/list/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/list/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/list/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/list/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/list/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/list/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/list/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/list/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/list/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/list/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/list/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/list/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/list/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/list/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/list/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/list/runtime/components/list.js b/packages/ui/dist/copy/list/runtime/components/list.js index 247cffcc3..88efde471 100644 --- a/packages/ui/dist/copy/list/runtime/components/list.js +++ b/packages/ui/dist/copy/list/runtime/components/list.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/list.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/list.js var J3w1List = class extends J3w1Element { static componentId = "list"; static version = "4.0.0"; - static implementationId = "sha256-14u9zr26qx+pniqBnH8sp+D6R9pyXRKm+KsUR/WnsOU="; + static implementationId = "sha256-FLV30YCWvaLCp8wYMYz2Pjn6EATLZku0Y+JC3EzTq3o="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1List }; diff --git a/packages/ui/dist/copy/list/runtime/register/list.js b/packages/ui/dist/copy/list/runtime/register/list.js index 2642fae97..abf1291e3 100644 --- a/packages/ui/dist/copy/list/runtime/register/list.js +++ b/packages/ui/dist/copy/list/runtime/register/list.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1List } from "../components/list.js"; -//#region .cache/ui-build/entries/register/list.js +// .cache/ui-build/entries/register/list.js var element = registerElement("j3w1-list", J3w1List); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/loading-indicator/manifest.json b/packages/ui/dist/copy/loading-indicator/manifest.json index 221bca48b..79b025894 100644 --- a/packages/ui/dist/copy/loading-indicator/manifest.json +++ b/packages/ui/dist/copy/loading-indicator/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/loading-indicator.md", "dependencies": [ "register/loading-indicator.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/loading-indicator.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/loading-indicator.js": "sha256-HHn/Y10+qdiLQ3DUo5i5OEHDhfg4ViJo8nI4ie7dJps=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/loading-indicator.js": "sha256-Z0q8XmSpQgrwC0AcFNlCQIZSt8tVvZ/ZF6McNG1rtBo=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/loading-indicator.js": "sha256-GksNrn8rJ9nRV9W+CbRKOa2vwUiQFLyqYpbcADyKm/I=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/loading-indicator.js": "sha256-1NsGiis031LwfMAwIj+8bNdvBPObvwdaJgoF3JXNGhg=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-ombtuuRs2PXpBfR+/B6paDohN3ODM1V0aNbRSzOcrmQ=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/loading-indicator/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/loading-indicator/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/loading-indicator/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/loading-indicator/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/loading-indicator/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/loading-indicator/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/loading-indicator/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/loading-indicator/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/loading-indicator/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/loading-indicator/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/loading-indicator/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/loading-indicator/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/loading-indicator/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/loading-indicator/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/loading-indicator/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/loading-indicator/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/loading-indicator/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/loading-indicator/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/loading-indicator/runtime/components/loading-indicator.js b/packages/ui/dist/copy/loading-indicator/runtime/components/loading-indicator.js index 85ead853a..3d697da29 100644 --- a/packages/ui/dist/copy/loading-indicator/runtime/components/loading-indicator.js +++ b/packages/ui/dist/copy/loading-indicator/runtime/components/loading-indicator.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/loading-indicator.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/loading-indicator.js var J3w1LoadingIndicator = class extends J3w1Element { static componentId = "loading-indicator"; static version = "4.0.0"; - static implementationId = "sha256-IeUo78vKcH/jhCptrFf5Js2XH0mNmrbHQA3dBow7Sb8="; + static implementationId = "sha256-8gayEmIQL3leNhAhX4uqlnyCPN/wDa2q0DkoydIe+k0="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1LoadingIndicator }; diff --git a/packages/ui/dist/copy/loading-indicator/runtime/register/loading-indicator.js b/packages/ui/dist/copy/loading-indicator/runtime/register/loading-indicator.js index 5e3a0b442..30ec8f3a6 100644 --- a/packages/ui/dist/copy/loading-indicator/runtime/register/loading-indicator.js +++ b/packages/ui/dist/copy/loading-indicator/runtime/register/loading-indicator.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1LoadingIndicator } from "../components/loading-indicator.js"; -//#region .cache/ui-build/entries/register/loading-indicator.js +// .cache/ui-build/entries/register/loading-indicator.js var element = registerElement("j3w1-loading-indicator", J3w1LoadingIndicator); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/menu/manifest.json b/packages/ui/dist/copy/menu/manifest.json index 7386d6b0b..364811cc2 100644 --- a/packages/ui/dist/copy/menu/manifest.json +++ b/packages/ui/dist/copy/menu/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/menu.md", "dependencies": [ "register/menu.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/menu.js", - "chunks/navigation-BfNzDYZB.js" + "chunks/navigation-CknoksQ5.js" ], "files": { - "runtime/register/menu.js": "sha256-6CvU7Rei9lC+olXvluxdbCPqh46GrPSvB2MGiudiMTk=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/menu.js": "sha256-As/aVex/jKXrmY4x/rG0tVMVUij8ZLPXK0kKS4ZBpSQ=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", + "runtime/register/menu.js": "sha256-du/4u8ykElicgf7iZHv6rD5yz/4njOxzodjcqCcr0d8=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/menu.js": "sha256-qz11rQvGk4omYnKEFWVz4SXD3R4xn/UhG0nt4oqFtJw=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-k4+o5GOHUM88StftYskfdyFUCI7mkb7z/Q98q6IVoLs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/menu/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/menu/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/menu/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/menu/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/menu/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/menu/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/menu/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/menu/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/menu/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/menu/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/menu/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/menu/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/menu/runtime/chunks/navigation-BfNzDYZB.js b/packages/ui/dist/copy/menu/runtime/chunks/navigation-BfNzDYZB.js deleted file mode 100644 index db2779553..000000000 --- a/packages/ui/dist/copy/menu/runtime/chunks/navigation-BfNzDYZB.js +++ /dev/null @@ -1,377 +0,0 @@ -import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/navigation.js -function tabs(root, { on }, listOverride) { - const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); - if (!list) return {}; - const items = () => all(list, "[role=\"tab\"]").filter(enabled); - const select = (id, focus = false) => { - const tab = items().find((item) => item.id === id); - if (!tab) throw new RangeError(`Unknown enabled tab: ${id}`); - all(list, "[role=\"tab\"]").forEach((item) => { - item.setAttribute("aria-selected", String(item === tab)); - item.tabIndex = item === tab ? 0 : -1; - }); - all(root, "[role=\"tabpanel\"]").filter((panel) => all(list, "[role=\"tab\"]").some((tab) => tab.getAttribute("aria-controls") === panel.id)).forEach((panel) => { - panel.hidden = panel.id !== tab.getAttribute("aria-controls"); - if (!panel.hidden && !panel.querySelector("a[href],button,input,select,textarea,[tabindex='0']")) panel.tabIndex = 0; - }); - if (focus) tab.focus(); - return tab; - }; - const activate = (tab) => { - select(tab.id); - root.emit("select", { - id: tab.id, - panelId: tab.getAttribute("aria-controls") - }); - }; - on(list, "click", (event) => { - const tab = event.target.closest("[role=\"tab\"]"); - if (tab && enabled(tab)) activate(tab); - }); - on(list, "keydown", (event) => { - const current = event.target.closest("[role=\"tab\"]"), options = items(); - if (!current) return; - const vertical = list.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(list).direction === "rtl"; - const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", previous = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; - let index = options.indexOf(current); - if (event.key === next) index++; - else if (event.key === previous) index--; - else if (event.key === "Home") index = 0; - else if (event.key === "End") index = options.length - 1; - else if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - activate(current); - return; - } else return; - event.preventDefault(); - const tab = rove(options, index); - if (root.getAttribute("activation") !== "manual") activate(tab); - }); - const initial = items().find((item) => item.getAttribute("aria-selected") === "true") ?? items()[0]; - if (initial) select(initial.id); - return { - select, - get selectedId() { - return list.querySelector("[aria-selected=\"true\"]")?.id ?? ""; - }, - set selectedId(id) { - select(id); - } - }; -} -function toolbar(root, { on }) { - const bar = root.querySelector("[role=\"toolbar\"]"); - if (!bar) return {}; - const controls = () => all(bar, "button,a[href],input,select").filter((node) => enabled(node) && visible(node) && !node.closest("[role=\"menu\"]")); - const initial = controls(); - rove(initial, Math.max(0, initial.findIndex((node) => node.tabIndex === 0)), false); - on(bar, "focusin", (event) => { - if (controls().includes(event.target)) rove(controls(), controls().indexOf(event.target), false); - }); - on(bar, "keydown", (event) => { - if (event.target.matches("input,select,textarea") || event.target.closest("[role=\"menu\"]")) return; - const items = controls(), index = items.indexOf(event.target); - const vertical = bar.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(bar).direction === "rtl"; - const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", prev = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; - if (![ - next, - prev, - "Home", - "End" - ].includes(event.key)) return; - event.preventDefault(); - rove(items, keyIndex({ - key: event.key, - index, - length: items.length, - next, - previous: prev - })); - }); - on(bar, "click", (event) => { - const button = event.target.closest("button[aria-pressed]"); - if (button && enabled(button)) { - button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - root.emit("action", { - action: button.dataset.action ?? button.textContent.trim(), - pressed: button.getAttribute("aria-pressed") === "true" - }); - } - }); - return {}; -} -function disclosure(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button[aria-controls][aria-expanded]"); - if (!button || !enabled(button)) return; - const target = root.querySelector(`#${CSS.escape(button.getAttribute("aria-controls"))}`); - if (!target) return; - const expanded = button.getAttribute("aria-expanded") !== "true"; - button.setAttribute("aria-expanded", String(expanded)); - target.hidden = !expanded; - root.emit("toggle", { - id: target.id, - expanded - }); - }); - const details = root.querySelector("details"); - on(details, "toggle", () => root.emit("toggle", { - id: details.id, - expanded: details.open - })); - return { - get open() { - return details?.open ?? false; - }, - set open(value) { - if (details) details.open = Boolean(value); - } - }; -} -function combobox(root, { on, signal }) { - const input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"); - if (!input || !list) return {}; - identify(root, list, "options"); - input.setAttribute("aria-controls", list.id); - let active = null, notifying = false; - const notify = () => { - notifying = true; - try { - nativeInput(input); - nativeInput(input, "change"); - } finally { - notifying = false; - } - }; - const options = () => all(list, "[role=\"option\"]").filter((node) => enabled(node) && !node.hidden && !node.closest("[role=\"group\"][hidden]")); - all(list, "[role=\"option\"]").forEach((option, index) => identify(root, option, `option-${index}`)); - const setActive = (option) => { - active = option; - all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); - if (option) { - input.setAttribute("aria-activedescendant", option.id); - option.scrollIntoView({ block: "nearest" }); - } else input.removeAttribute("aria-activedescendant"); - }; - const hide = () => { - list.hidden = true; - input.setAttribute("aria-expanded", "false"); - setActive(null); - }; - const filter = (query = input.value) => { - for (const option of all(list, "[role=\"option\"]")) if (enabled(option)) option.hidden = !option.textContent.toLocaleLowerCase().includes(query.toLocaleLowerCase()); - all(list, "[role=\"group\"]").forEach((group) => { - group.hidden = !all(group, "[role=\"option\"]").some((node) => enabled(node) && !node.hidden); - }); - const empty = root.querySelector(".combobox-empty"); - if (empty) { - empty.hidden = options().length !== 0; - empty.classList.toggle("combobox-empty-shown", !empty.hidden); - } - if (!options().includes(active)) setActive(null); - }; - const show = (allOptions = false) => { - if (!enabled(input) || input.readOnly) return; - filter(allOptions ? "" : input.value); - list.hidden = false; - input.setAttribute("aria-expanded", "true"); - place(input, list); - }; - const choose = (option) => { - if (!option || !enabled(option)) return; - input.value = option.dataset.value ?? option.textContent.trim(); - hide(); - notify(); - input.focus(); - }; - on(input, "input", () => { - if (!notifying) { - show(); - announce(root, `${options().length} options available.`); - } - }); - on(input, "keydown", (event) => { - if (event.key === "Tab") { - hide(); - return; - } - if (event.key === "Escape") { - if (!list.hidden) { - hide(); - event.stopPropagation(); - } else if (input.value) { - input.value = ""; - notify(); - event.stopPropagation(); - } - event.preventDefault(); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - hide(); - return; - } - if (["ArrowDown", "ArrowUp"].includes(event.key)) { - event.preventDefault(); - if (list.hidden) show(true); - if (event.altKey) return; - const items = options(), index = active ? items.indexOf(active) : event.key === "ArrowDown" ? -1 : 0; - if (items.length) setActive(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); - } else if (event.key === "Enter" && !list.hidden && active) { - event.preventDefault(); - choose(active); - } - }); - on(list, "pointerdown", (event) => { - if (event.target.closest("[role=\"option\"]")) event.preventDefault(); - }); - on(list, "click", (event) => choose(event.target.closest("[role=\"option\"]"))); - on(root.querySelector(".combobox-toggle"), "click", () => { - list.hidden ? show(true) : hide(); - input.focus(); - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!root.contains(event.target)) hide(); - }); - on(root, "focusout", () => queueMicrotask(() => { - if (!signal.aborted && !root.contains(root.ownerDocument.activeElement)) hide(); - })); - on(root.ownerDocument.defaultView, "resize", () => { - if (!list.hidden) place(input, list); - }); - on(root.ownerDocument, "scroll", (event) => { - if (!list.hidden && !list.contains(event.target)) place(input, list); - }, { capture: true }); - hide(); - return { - show, - hide, - get open() { - return !list.hidden; - }, - set open(value) { - value ? show() : hide(); - }, - get value() { - return input.value; - }, - set value(value) { - input.value = String(value ?? ""); - if (!list.hidden) filter(); - }, - cleanup: hide - }; -} -function menu(root, { on }) { - const trigger = root.querySelector("button[aria-haspopup=\"menu\"]"), main = root.querySelector("[role=\"menu\"]"); - if (!trigger || !main) return {}; - identify(root, main, "menu"); - trigger.setAttribute("aria-controls", main.id); - const lists = all(root, "[role=\"menu\"]"); - const items = (list) => all(list, "[role^=\"menuitem\"]").filter((item) => item.closest("[role=\"menu\"]") === list); - const controller = (list) => all(root, "[aria-controls]").find((node) => node.getAttribute("aria-controls") === list.id); - const closeList = (list) => { - list.hidden = true; - controller(list)?.setAttribute("aria-expanded", "false"); - }; - const hide = (focus = true) => { - lists.forEach(closeList); - if (focus) trigger.focus(); - }; - const showList = (list, button, last = false) => { - list.hidden = false; - button.setAttribute("aria-expanded", "true"); - place(button, list); - rove(items(list), last ? items(list).length - 1 : 0); - }; - const show = () => { - if (enabled(trigger)) showList(main, trigger); - }; - const submenu = (button) => button.hasAttribute("aria-haspopup") ? lists.find((list) => list.id === button.getAttribute("aria-controls")) : null; - const activate = (item) => { - if (!enabled(item)) return; - const child = submenu(item); - if (child) { - showList(child, item); - return; - } - if (item.getAttribute("role") === "menuitemcheckbox") item.setAttribute("aria-checked", String(item.getAttribute("aria-checked") !== "true")); - else if (item.getAttribute("role") === "menuitemradio") items(item.closest("[role=\"menu\"]")).filter((node) => node.getAttribute("role") === "menuitemradio").forEach((node) => node.setAttribute("aria-checked", String(node === item))); - else hide(); - root.emit("action", { - action: item.dataset.action ?? item.textContent.trim(), - checked: item.getAttribute("aria-checked") === "true" - }); - }; - on(trigger, "click", () => main.hidden ? show() : hide()); - on(trigger, "keydown", (event) => { - if (["ArrowDown", "ArrowUp"].includes(event.key) && enabled(trigger)) { - event.preventDefault(); - showList(main, trigger, event.key === "ArrowUp"); - } - }); - on(root, "click", (event) => { - const item = event.target.closest("[role^=\"menuitem\"]"); - if (item) activate(item); - }); - on(root, "keydown", (event) => { - const item = event.target.closest("[role^=\"menuitem\"]"); - if (!item) return; - const list = item.closest("[role=\"menu\"]"), options = items(list), index = options.indexOf(item), rtl = getComputedStyle(list).direction === "rtl"; - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - rove(options, keyIndex({ - key: event.key, - index, - length: options.length - })); - } else if (event.key === "Escape" || event.key === (rtl ? "ArrowRight" : "ArrowLeft") && list !== main) { - event.preventDefault(); - event.stopPropagation(); - if (list !== main) { - closeList(list); - controller(list)?.focus(); - } else hide(); - } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight") && submenu(item)) { - event.preventDefault(); - showList(submenu(item), item); - } else if (event.key === "Tab") hide(); - else if (event.key.length === 1 && /\S/.test(event.key)) { - const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(".menu-label") ?? node).textContent.trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); - if (found) { - event.preventDefault(); - rove(options, options.indexOf(found)); - } - } - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!root.contains(event.target)) hide(false); - }); - on(root.ownerDocument, "focusin", (event) => { - if (!root.contains(event.target)) hide(false); - }); - on(root.ownerDocument.defaultView, "resize", () => lists.filter((list) => !list.hidden).forEach((list) => place(controller(list), list))); - hide(false); - return { - show, - hide, - get open() { - return !main.hidden; - }, - set open(value) { - value ? show() : hide(false); - }, - cleanup() { - hide(false); - } - }; -} -//#endregion -export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/menu/runtime/chunks/navigation-CknoksQ5.js b/packages/ui/dist/copy/menu/runtime/chunks/navigation-CknoksQ5.js new file mode 100644 index 000000000..dfd1883e6 --- /dev/null +++ b/packages/ui/dist/copy/menu/runtime/chunks/navigation-CknoksQ5.js @@ -0,0 +1,376 @@ +import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/navigation.js +function tabs(root, { on }, listOverride) { + const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); + if (!list) return {}; + const items = () => all(list, "[role=\"tab\"]").filter(enabled); + const select = (id, focus = false) => { + const tab = items().find((item) => item.id === id); + if (!tab) throw new RangeError(`Unknown enabled tab: ${id}`); + all(list, "[role=\"tab\"]").forEach((item) => { + item.setAttribute("aria-selected", String(item === tab)); + item.tabIndex = item === tab ? 0 : -1; + }); + all(root, "[role=\"tabpanel\"]").filter((panel) => all(list, "[role=\"tab\"]").some((tab) => tab.getAttribute("aria-controls") === panel.id)).forEach((panel) => { + panel.hidden = panel.id !== tab.getAttribute("aria-controls"); + if (!panel.hidden && !panel.querySelector("a[href],button,input,select,textarea,[tabindex='0']")) panel.tabIndex = 0; + }); + if (focus) tab.focus(); + return tab; + }; + const activate = (tab) => { + select(tab.id); + root.emit("select", { + id: tab.id, + panelId: tab.getAttribute("aria-controls") + }); + }; + on(list, "click", (event) => { + const tab = event.target.closest("[role=\"tab\"]"); + if (tab && enabled(tab)) activate(tab); + }); + on(list, "keydown", (event) => { + const current = event.target.closest("[role=\"tab\"]"), options = items(); + if (!current) return; + const vertical = list.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(list).direction === "rtl"; + const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", previous = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; + let index = options.indexOf(current); + if (event.key === next) index++; + else if (event.key === previous) index--; + else if (event.key === "Home") index = 0; + else if (event.key === "End") index = options.length - 1; + else if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + activate(current); + return; + } else return; + event.preventDefault(); + const tab = rove(options, index); + if (root.getAttribute("activation") !== "manual") activate(tab); + }); + const initial = items().find((item) => item.getAttribute("aria-selected") === "true") ?? items()[0]; + if (initial) select(initial.id); + return { + select, + get selectedId() { + return list.querySelector("[aria-selected=\"true\"]")?.id ?? ""; + }, + set selectedId(id) { + select(id); + } + }; +} +function toolbar(root, { on }) { + const bar = root.querySelector("[role=\"toolbar\"]"); + if (!bar) return {}; + const controls = () => all(bar, "button,a[href],input,select").filter((node) => enabled(node) && visible(node) && !node.closest("[role=\"menu\"]")); + const initial = controls(); + rove(initial, Math.max(0, initial.findIndex((node) => node.tabIndex === 0)), false); + on(bar, "focusin", (event) => { + if (controls().includes(event.target)) rove(controls(), controls().indexOf(event.target), false); + }); + on(bar, "keydown", (event) => { + if (event.target.matches("input,select,textarea") || event.target.closest("[role=\"menu\"]")) return; + const items = controls(), index = items.indexOf(event.target); + const vertical = bar.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(bar).direction === "rtl"; + const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", prev = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; + if (![ + next, + prev, + "Home", + "End" + ].includes(event.key)) return; + event.preventDefault(); + rove(items, keyIndex({ + key: event.key, + index, + length: items.length, + next, + previous: prev + })); + }); + on(bar, "click", (event) => { + const button = event.target.closest("button[aria-pressed]"); + if (button && enabled(button)) { + button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + root.emit("action", { + action: button.dataset.action ?? button.textContent.trim(), + pressed: button.getAttribute("aria-pressed") === "true" + }); + } + }); + return {}; +} +function disclosure(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button[aria-controls][aria-expanded]"); + if (!button || !enabled(button)) return; + const target = root.querySelector(`#${CSS.escape(button.getAttribute("aria-controls"))}`); + if (!target) return; + const expanded = button.getAttribute("aria-expanded") !== "true"; + button.setAttribute("aria-expanded", String(expanded)); + target.hidden = !expanded; + root.emit("toggle", { + id: target.id, + expanded + }); + }); + const details = root.querySelector("details"); + on(details, "toggle", () => root.emit("toggle", { + id: details.id, + expanded: details.open + })); + return { + get open() { + return details?.open ?? false; + }, + set open(value) { + if (details) details.open = Boolean(value); + } + }; +} +function combobox(root, { on, signal }) { + const input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"); + if (!input || !list) return {}; + identify(root, list, "options"); + input.setAttribute("aria-controls", list.id); + let active = null, notifying = false; + const notify = () => { + notifying = true; + try { + nativeInput(input); + nativeInput(input, "change"); + } finally { + notifying = false; + } + }; + const options = () => all(list, "[role=\"option\"]").filter((node) => enabled(node) && !node.hidden && !node.closest("[role=\"group\"][hidden]")); + all(list, "[role=\"option\"]").forEach((option, index) => identify(root, option, `option-${index}`)); + const setActive = (option) => { + active = option; + all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); + if (option) { + input.setAttribute("aria-activedescendant", option.id); + option.scrollIntoView({ block: "nearest" }); + } else input.removeAttribute("aria-activedescendant"); + }; + const hide = () => { + list.hidden = true; + input.setAttribute("aria-expanded", "false"); + setActive(null); + }; + const filter = (query = input.value) => { + for (const option of all(list, "[role=\"option\"]")) if (enabled(option)) option.hidden = !option.textContent.toLocaleLowerCase().includes(query.toLocaleLowerCase()); + all(list, "[role=\"group\"]").forEach((group) => { + group.hidden = !all(group, "[role=\"option\"]").some((node) => enabled(node) && !node.hidden); + }); + const empty = root.querySelector(".combobox-empty"); + if (empty) { + empty.hidden = options().length !== 0; + empty.classList.toggle("combobox-empty-shown", !empty.hidden); + } + if (!options().includes(active)) setActive(null); + }; + const show = (allOptions = false) => { + if (!enabled(input) || input.readOnly) return; + filter(allOptions ? "" : input.value); + list.hidden = false; + input.setAttribute("aria-expanded", "true"); + place(input, list); + }; + const choose = (option) => { + if (!option || !enabled(option)) return; + input.value = option.dataset.value ?? option.textContent.trim(); + hide(); + notify(); + input.focus(); + }; + on(input, "input", () => { + if (!notifying) { + show(); + announce(root, `${options().length} options available.`); + } + }); + on(input, "keydown", (event) => { + if (event.key === "Tab") { + hide(); + return; + } + if (event.key === "Escape") { + if (!list.hidden) { + hide(); + event.stopPropagation(); + } else if (input.value) { + input.value = ""; + notify(); + event.stopPropagation(); + } + event.preventDefault(); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + hide(); + return; + } + if (["ArrowDown", "ArrowUp"].includes(event.key)) { + event.preventDefault(); + if (list.hidden) show(true); + if (event.altKey) return; + const items = options(), index = active ? items.indexOf(active) : event.key === "ArrowDown" ? -1 : 0; + if (items.length) setActive(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); + } else if (event.key === "Enter" && !list.hidden && active) { + event.preventDefault(); + choose(active); + } + }); + on(list, "pointerdown", (event) => { + if (event.target.closest("[role=\"option\"]")) event.preventDefault(); + }); + on(list, "click", (event) => choose(event.target.closest("[role=\"option\"]"))); + on(root.querySelector(".combobox-toggle"), "click", () => { + list.hidden ? show(true) : hide(); + input.focus(); + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!root.contains(event.target)) hide(); + }); + on(root, "focusout", () => queueMicrotask(() => { + if (!signal.aborted && !root.contains(root.ownerDocument.activeElement)) hide(); + })); + on(root.ownerDocument.defaultView, "resize", () => { + if (!list.hidden) place(input, list); + }); + on(root.ownerDocument, "scroll", (event) => { + if (!list.hidden && !list.contains(event.target)) place(input, list); + }, { capture: true }); + hide(); + return { + show, + hide, + get open() { + return !list.hidden; + }, + set open(value) { + value ? show() : hide(); + }, + get value() { + return input.value; + }, + set value(value) { + input.value = String(value ?? ""); + if (!list.hidden) filter(); + }, + cleanup: hide + }; +} +function menu(root, { on }) { + const trigger = root.querySelector("button[aria-haspopup=\"menu\"]"), main = root.querySelector("[role=\"menu\"]"); + if (!trigger || !main) return {}; + identify(root, main, "menu"); + trigger.setAttribute("aria-controls", main.id); + const lists = all(root, "[role=\"menu\"]"); + const items = (list) => all(list, "[role^=\"menuitem\"]").filter((item) => item.closest("[role=\"menu\"]") === list); + const controller = (list) => all(root, "[aria-controls]").find((node) => node.getAttribute("aria-controls") === list.id); + const closeList = (list) => { + list.hidden = true; + controller(list)?.setAttribute("aria-expanded", "false"); + }; + const hide = (focus = true) => { + lists.forEach(closeList); + if (focus) trigger.focus(); + }; + const showList = (list, button, last = false) => { + list.hidden = false; + button.setAttribute("aria-expanded", "true"); + place(button, list); + rove(items(list), last ? items(list).length - 1 : 0); + }; + const show = () => { + if (enabled(trigger)) showList(main, trigger); + }; + const submenu = (button) => button.hasAttribute("aria-haspopup") ? lists.find((list) => list.id === button.getAttribute("aria-controls")) : null; + const activate = (item) => { + if (!enabled(item)) return; + const child = submenu(item); + if (child) { + showList(child, item); + return; + } + if (item.getAttribute("role") === "menuitemcheckbox") item.setAttribute("aria-checked", String(item.getAttribute("aria-checked") !== "true")); + else if (item.getAttribute("role") === "menuitemradio") items(item.closest("[role=\"menu\"]")).filter((node) => node.getAttribute("role") === "menuitemradio").forEach((node) => node.setAttribute("aria-checked", String(node === item))); + else hide(); + root.emit("action", { + action: item.dataset.action ?? item.textContent.trim(), + checked: item.getAttribute("aria-checked") === "true" + }); + }; + on(trigger, "click", () => main.hidden ? show() : hide()); + on(trigger, "keydown", (event) => { + if (["ArrowDown", "ArrowUp"].includes(event.key) && enabled(trigger)) { + event.preventDefault(); + showList(main, trigger, event.key === "ArrowUp"); + } + }); + on(root, "click", (event) => { + const item = event.target.closest("[role^=\"menuitem\"]"); + if (item) activate(item); + }); + on(root, "keydown", (event) => { + const item = event.target.closest("[role^=\"menuitem\"]"); + if (!item) return; + const list = item.closest("[role=\"menu\"]"), options = items(list), index = options.indexOf(item), rtl = getComputedStyle(list).direction === "rtl"; + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + rove(options, keyIndex({ + key: event.key, + index, + length: options.length + })); + } else if (event.key === "Escape" || event.key === (rtl ? "ArrowRight" : "ArrowLeft") && list !== main) { + event.preventDefault(); + event.stopPropagation(); + if (list !== main) { + closeList(list); + controller(list)?.focus(); + } else hide(); + } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight") && submenu(item)) { + event.preventDefault(); + showList(submenu(item), item); + } else if (event.key === "Tab") hide(); + else if (event.key.length === 1 && /\S/.test(event.key)) { + const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(".menu-label") ?? node).textContent.trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); + if (found) { + event.preventDefault(); + rove(options, options.indexOf(found)); + } + } + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!root.contains(event.target)) hide(false); + }); + on(root.ownerDocument, "focusin", (event) => { + if (!root.contains(event.target)) hide(false); + }); + on(root.ownerDocument.defaultView, "resize", () => lists.filter((list) => !list.hidden).forEach((list) => place(controller(list), list))); + hide(false); + return { + show, + hide, + get open() { + return !main.hidden; + }, + set open(value) { + value ? show() : hide(false); + }, + cleanup() { + hide(false); + } + }; +} +export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/menu/runtime/components/menu.js b/packages/ui/dist/copy/menu/runtime/components/menu.js index b35ceb43e..b7031703c 100644 --- a/packages/ui/dist/copy/menu/runtime/components/menu.js +++ b/packages/ui/dist/copy/menu/runtime/components/menu.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as menu } from "../chunks/navigation-BfNzDYZB.js"; -//#region .cache/ui-build/entries/components/menu.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as menu } from "../chunks/navigation-CknoksQ5.js"; +// .cache/ui-build/entries/components/menu.js var J3w1Menu = class extends J3w1Element { static componentId = "menu"; static version = "4.0.0"; - static implementationId = "sha256-oS0Ubl9rLRKcmk22aO7KDARBpUoA/Y7sR2AvyqabH+U="; + static implementationId = "sha256-eK7xkdMDWtplCwL1L9Yt83xHvFQIuO3z1yoixK4RXOo="; static connect = menu; static upgradeProperties = [ "disabled", @@ -32,5 +32,4 @@ var J3w1Menu = class extends J3w1Element { }); } }; -//#endregion export { J3w1Menu }; diff --git a/packages/ui/dist/copy/menu/runtime/register/menu.js b/packages/ui/dist/copy/menu/runtime/register/menu.js index 655b77a5a..e99b1d3df 100644 --- a/packages/ui/dist/copy/menu/runtime/register/menu.js +++ b/packages/ui/dist/copy/menu/runtime/register/menu.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Menu } from "../components/menu.js"; -//#region .cache/ui-build/entries/register/menu.js +// .cache/ui-build/entries/register/menu.js var element = registerElement("j3w1-menu", J3w1Menu); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/multiselect/manifest.json b/packages/ui/dist/copy/multiselect/manifest.json index e5b2646cb..6cb6b89d9 100644 --- a/packages/ui/dist/copy/multiselect/manifest.json +++ b/packages/ui/dist/copy/multiselect/manifest.json @@ -5,19 +5,19 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/multiselect.md", "dependencies": [ "register/multiselect.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/multiselect.js", - "chunks/advanced-CqBF0dSb.js", - "chunks/markup-DeQ4bEMR.js" + "chunks/advanced-BrFnVc0y.js", + "chunks/markup-AopKpwOF.js" ], "files": { - "runtime/register/multiselect.js": "sha256-GvsBeg69jcyZ7oEUVcCdn1MKUx1TUf7RIO5QVAsXGH4=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/multiselect.js": "sha256-MllSXtT35z9jg4cXDS6YzVpSLSEHEdFav9snvf+mVPU=", - "runtime/chunks/advanced-CqBF0dSb.js": "sha256-ozOzkRU6IeVGBqU3XQ0aLledkAi9vcs8dJdMQutVevs=", - "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", + "runtime/register/multiselect.js": "sha256-1WE2XkDVU0w3W2wKz7GsaPQoHNCsroAW8HcfzuJg7Cw=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/multiselect.js": "sha256-sPp8OqCzF9v0hsxG/mWdadkKOIW//gyZ/Bng4A5c//Y=", + "runtime/chunks/advanced-BrFnVc0y.js": "sha256-FVberBpKO49P/WGnxa61BTxhYsLnnvMFInur/TwjG44=", + "runtime/chunks/markup-AopKpwOF.js": "sha256-/Dn3cWEmlRQzeQAPVf+C0AooVb1pdIQeNeqd1fQVoPc=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-mNyp6sPjM1B458gp8a1MSGzOFHVesIqX8cVV9P3tth0=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/multiselect/runtime/chunks/advanced-CqBF0dSb.js b/packages/ui/dist/copy/multiselect/runtime/chunks/advanced-BrFnVc0y.js similarity index 98% rename from packages/ui/dist/copy/multiselect/runtime/chunks/advanced-CqBF0dSb.js rename to packages/ui/dist/copy/multiselect/runtime/chunks/advanced-BrFnVc0y.js index 4a5c45981..36e7638c4 100644 --- a/packages/ui/dist/copy/multiselect/runtime/chunks/advanced-CqBF0dSb.js +++ b/packages/ui/dist/copy/multiselect/runtime/chunks/advanced-BrFnVc0y.js @@ -1,6 +1,6 @@ -import { c as keyIndex, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-B7mo5Eq3.js"; -import { t as IDREFS } from "./markup-DeQ4bEMR.js"; -//#region packages/ui/src/behaviors/advanced.js +import { c as keyIndex, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-DqwWT5pJ.js"; +import { t as IDREFS } from "./markup-AopKpwOF.js"; +// packages/ui/src/behaviors/advanced.js function tree(root, { on }) { const treeRoot = root.querySelector("[role=\"tree\"]"); if (!treeRoot) return {}; @@ -341,5 +341,4 @@ function commandPalette(root, { on }) { cleanup: close }; } -//#endregion export { tree as i, multiselect as n, repeater as r, commandPalette as t }; diff --git a/packages/ui/dist/copy/multiselect/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/multiselect/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/multiselect/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/multiselect/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/multiselect/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/multiselect/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/multiselect/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/multiselect/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/multiselect/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/multiselect/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/multiselect/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/multiselect/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/multiselect/runtime/chunks/markup-AopKpwOF.js b/packages/ui/dist/copy/multiselect/runtime/chunks/markup-AopKpwOF.js new file mode 100644 index 000000000..bc1c52c0b --- /dev/null +++ b/packages/ui/dist/copy/multiselect/runtime/chunks/markup-AopKpwOF.js @@ -0,0 +1,53 @@ +// scripts/lib/markup.mjs +var IDREFS = /* @__PURE__ */ new Set([ + "for", + "form", + "list", + "aria-labelledby", + "aria-describedby", + "aria-controls", + "aria-owns", + "aria-activedescendant", + "aria-details", + "aria-errormessage", + "headers" +]); +var walkMarkup = (node, visit) => { + visit(node); + for (const child of node.childNodes ?? []) walkMarkup(child, visit); + if (node.tagName === "template" && node.content) walkMarkup(node.content, visit); +}; +var attribute = (node, name) => node.attrs?.find((a) => a.name === name)?.value; +var setAttribute = (node, name, value = "") => { + if (!node?.attrs) return; + const current = node.attrs.find((a) => a.name === name); + if (current) current.value = value; + else node.attrs.push({ + name, + value + }); +}; +var removeAttribute = (node, name) => { + if (node.attrs) node.attrs = node.attrs.filter((a) => a.name !== name); +}; +var hasClass = (node, name) => attribute(node, "class")?.split(/\s+/).includes(name) ?? false; +var namespaceMarkup = (tree, decorate, { strict = true, renameNames = false } = {}) => { + const ids = /* @__PURE__ */ new Map(); + walkMarkup(tree, (node) => { + const id = attribute(node, "id"); + if (id === void 0) return; + if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(id) || ids.has(id)) throw new Error(`Invalid or duplicate markup ID: ${id}`); + ids.set(id, decorate(id)); + }); + const reference = (id) => { + if (!ids.has(id) && strict) throw new Error(`Unresolved markup ID reference: ${id}`); + return ids.get(id) ?? decorate(id); + }; + walkMarkup(tree, (node) => { + for (const attr of node.attrs ?? []) if (attr.name === "id") attr.value = reference(attr.value); + else if (IDREFS.has(attr.name)) attr.value = attr.value.trim().split(/\s+/).map(reference).join(" "); + else if (attr.name === "href" && attr.value.startsWith("#")) attr.value = `#${reference(attr.value.slice(1))}`; + else if (renameNames && attr.name === "name") attr.value = decorate(attr.value); + }); +}; +export { setAttribute as a, removeAttribute as i, hasClass as n, walkMarkup as o, namespaceMarkup as r, IDREFS as t }; diff --git a/packages/ui/dist/copy/multiselect/runtime/chunks/markup-DeQ4bEMR.js b/packages/ui/dist/copy/multiselect/runtime/chunks/markup-DeQ4bEMR.js deleted file mode 100644 index 77bd9471d..000000000 --- a/packages/ui/dist/copy/multiselect/runtime/chunks/markup-DeQ4bEMR.js +++ /dev/null @@ -1,54 +0,0 @@ -//#region scripts/lib/markup.mjs -var IDREFS = /* @__PURE__ */ new Set([ - "for", - "form", - "list", - "aria-labelledby", - "aria-describedby", - "aria-controls", - "aria-owns", - "aria-activedescendant", - "aria-details", - "aria-errormessage", - "headers" -]); -var walkMarkup = (node, visit) => { - visit(node); - for (const child of node.childNodes ?? []) walkMarkup(child, visit); - if (node.tagName === "template" && node.content) walkMarkup(node.content, visit); -}; -var attribute = (node, name) => node.attrs?.find((a) => a.name === name)?.value; -var setAttribute = (node, name, value = "") => { - if (!node?.attrs) return; - const current = node.attrs.find((a) => a.name === name); - if (current) current.value = value; - else node.attrs.push({ - name, - value - }); -}; -var removeAttribute = (node, name) => { - if (node.attrs) node.attrs = node.attrs.filter((a) => a.name !== name); -}; -var hasClass = (node, name) => attribute(node, "class")?.split(/\s+/).includes(name) ?? false; -var namespaceMarkup = (tree, decorate, { strict = true, renameNames = false } = {}) => { - const ids = /* @__PURE__ */ new Map(); - walkMarkup(tree, (node) => { - const id = attribute(node, "id"); - if (id === void 0) return; - if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(id) || ids.has(id)) throw new Error(`Invalid or duplicate markup ID: ${id}`); - ids.set(id, decorate(id)); - }); - const reference = (id) => { - if (!ids.has(id) && strict) throw new Error(`Unresolved markup ID reference: ${id}`); - return ids.get(id) ?? decorate(id); - }; - walkMarkup(tree, (node) => { - for (const attr of node.attrs ?? []) if (attr.name === "id") attr.value = reference(attr.value); - else if (IDREFS.has(attr.name)) attr.value = attr.value.trim().split(/\s+/).map(reference).join(" "); - else if (attr.name === "href" && attr.value.startsWith("#")) attr.value = `#${reference(attr.value.slice(1))}`; - else if (renameNames && attr.name === "name") attr.value = decorate(attr.value); - }); -}; -//#endregion -export { setAttribute as a, removeAttribute as i, hasClass as n, walkMarkup as o, namespaceMarkup as r, IDREFS as t }; diff --git a/packages/ui/dist/copy/multiselect/runtime/components/multiselect.js b/packages/ui/dist/copy/multiselect/runtime/components/multiselect.js index cb58ac304..290c79dc8 100644 --- a/packages/ui/dist/copy/multiselect/runtime/components/multiselect.js +++ b/packages/ui/dist/copy/multiselect/runtime/components/multiselect.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as multiselect } from "../chunks/advanced-CqBF0dSb.js"; -//#region .cache/ui-build/entries/components/multiselect.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as multiselect } from "../chunks/advanced-BrFnVc0y.js"; +// .cache/ui-build/entries/components/multiselect.js var J3w1Multiselect = class extends J3w1Element { static componentId = "multiselect"; static version = "4.0.0"; - static implementationId = "sha256-M7eRaWl+u1uQgXFKvnBd0GCc8U7xIWfp5yT7U9eMjTg="; + static implementationId = "sha256-FXj0+g9cQaR/0ZBHov7023bXRTw6cKww+3uPo9AtwN8="; static connect = multiselect; static upgradeProperties = [ "disabled", @@ -28,5 +28,4 @@ var J3w1Multiselect = class extends J3w1Element { }); } }; -//#endregion export { J3w1Multiselect }; diff --git a/packages/ui/dist/copy/multiselect/runtime/register/multiselect.js b/packages/ui/dist/copy/multiselect/runtime/register/multiselect.js index 9183e5e5a..25b412f99 100644 --- a/packages/ui/dist/copy/multiselect/runtime/register/multiselect.js +++ b/packages/ui/dist/copy/multiselect/runtime/register/multiselect.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Multiselect } from "../components/multiselect.js"; -//#region .cache/ui-build/entries/register/multiselect.js +// .cache/ui-build/entries/register/multiselect.js var element = registerElement("j3w1-multiselect", J3w1Multiselect); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/number-field/manifest.json b/packages/ui/dist/copy/number-field/manifest.json index b102a62d2..0ae5b345f 100644 --- a/packages/ui/dist/copy/number-field/manifest.json +++ b/packages/ui/dist/copy/number-field/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/number-field.md", "dependencies": [ "register/number-field.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/number-field.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/number-field.js": "sha256-hzql0aRe655T+FCjYFhxlfYh24YEAwm8mSKqaRvncg8=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/number-field.js": "sha256-XejyUXzeklfHnLge+zZzoxBqpQGWSXtTLGhXpkm4Sew=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/number-field.js": "sha256-4H1AixN0gdK1WGkj5AboI6P6f1J+4eTI6guRQiLwdXo=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/number-field.js": "sha256-cR7uqb1y36rf/q2olUxijeTw76itQKlbAa+rFz+FJbc=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-XO8T0IBA7SNqfrL29Rr4KPOzxW7QYgRQVO5YJ59Rmbc=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/number-field/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/number-field/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/number-field/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/number-field/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/number-field/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/number-field/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/number-field/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/number-field/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/number-field/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/number-field/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/number-field/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/number-field/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/number-field/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/number-field/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/number-field/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/number-field/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/number-field/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/number-field/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/number-field/runtime/components/number-field.js b/packages/ui/dist/copy/number-field/runtime/components/number-field.js index 41733ea16..9efdf43c2 100644 --- a/packages/ui/dist/copy/number-field/runtime/components/number-field.js +++ b/packages/ui/dist/copy/number-field/runtime/components/number-field.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/number-field.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/number-field.js var J3w1NumberField = class extends J3w1Element { static componentId = "number-field"; static version = "4.0.0"; - static implementationId = "sha256-XSucS362OAqtU9RKAYp52Tc3M6K6uMWKmB6UdK8+/o0="; + static implementationId = "sha256-L91omcjZDDOb6GVo+J4RQqDwzG6TvC55C17ObqdffsA="; static connect = fields; static upgradeProperties = [ "disabled", @@ -31,5 +31,4 @@ var J3w1NumberField = class extends J3w1Element { return this._api.stepBy(...args); } }; -//#endregion export { J3w1NumberField }; diff --git a/packages/ui/dist/copy/number-field/runtime/register/number-field.js b/packages/ui/dist/copy/number-field/runtime/register/number-field.js index 8553c5a33..ed80b7832 100644 --- a/packages/ui/dist/copy/number-field/runtime/register/number-field.js +++ b/packages/ui/dist/copy/number-field/runtime/register/number-field.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1NumberField } from "../components/number-field.js"; -//#region .cache/ui-build/entries/register/number-field.js +// .cache/ui-build/entries/register/number-field.js var element = registerElement("j3w1-number-field", J3w1NumberField); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/pagination/manifest.json b/packages/ui/dist/copy/pagination/manifest.json index 6cd188a61..05fc586c4 100644 --- a/packages/ui/dist/copy/pagination/manifest.json +++ b/packages/ui/dist/copy/pagination/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/pagination.md", "dependencies": [ "register/pagination.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/pagination.js", - "chunks/tables-Cjr1EIJz.js" + "chunks/tables-zo8ebTOo.js" ], "files": { - "runtime/register/pagination.js": "sha256-brgdYKMAD7bcv2S/lK/pvq48lAK2y+31j4L/TNZAAAc=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/pagination.js": "sha256-B00TORk80D679cwO2BDfd3MFyKRhgzAoaWxrqC1AoYs=", - "runtime/chunks/tables-Cjr1EIJz.js": "sha256-K6BF6M6xNawgWdL+NIcBRZmY98j45o69tBI034Ks4Bg=", + "runtime/register/pagination.js": "sha256-Y/I0I6NpUS93DpmbrgeeMSQ6Qz20igQzG2hwhcqaEYo=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/pagination.js": "sha256-o7hAhquWpAuaROFwNjCnsuoFE1pRQZtC9jr6DPCoIuE=", + "runtime/chunks/tables-zo8ebTOo.js": "sha256-+LRPZmFKPk0oe8q3HDlfXCXkloBbkRbiFHVHczc3GEs=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-Y82QrGBuuCOolKEvjfgUe1uRkUY8RAPoLEiVsEUahxg=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/pagination/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/pagination/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/pagination/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/pagination/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/pagination/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/pagination/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/pagination/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/pagination/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/pagination/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/pagination/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/pagination/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/pagination/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/chunks/tables-Cjr1EIJz.js b/packages/ui/dist/copy/pagination/runtime/chunks/tables-zo8ebTOo.js similarity index 98% rename from packages/ui/dist/chunks/tables-Cjr1EIJz.js rename to packages/ui/dist/copy/pagination/runtime/chunks/tables-zo8ebTOo.js index f82aaf25e..56f7f3dc3 100644 --- a/packages/ui/dist/chunks/tables-Cjr1EIJz.js +++ b/packages/ui/dist/copy/pagination/runtime/chunks/tables-zo8ebTOo.js @@ -1,5 +1,5 @@ -import { c as keyIndex, f as rove, i as all, o as enabled, s as identify } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/tables.js +import { c as keyIndex, f as rove, i as all, o as enabled, s as identify } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/tables.js function table(root, { on }) { const element = root.querySelector("table"), body = element?.tBodies[0]; if (!element || !body) return {}; @@ -213,5 +213,4 @@ function pagination(root, { on }) { } }; } -//#endregion export { table as n, pagination as t }; diff --git a/packages/ui/dist/copy/pagination/runtime/components/pagination.js b/packages/ui/dist/copy/pagination/runtime/components/pagination.js index 140293f27..7423c292b 100644 --- a/packages/ui/dist/copy/pagination/runtime/components/pagination.js +++ b/packages/ui/dist/copy/pagination/runtime/components/pagination.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as pagination } from "../chunks/tables-Cjr1EIJz.js"; -//#region .cache/ui-build/entries/components/pagination.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as pagination } from "../chunks/tables-zo8ebTOo.js"; +// .cache/ui-build/entries/components/pagination.js var J3w1Pagination = class extends J3w1Element { static componentId = "pagination"; static version = "4.0.0"; - static implementationId = "sha256-HgWIYJ3ex0Ayw+BLic3BdN3dNV9ChkM7wiwgp/qkkAE="; + static implementationId = "sha256-MIZZYUoTVmPnN0QSV3/TqHlUbLXmXItH+lOBusJQhPQ="; static connect = pagination; static upgradeProperties = [ "disabled", @@ -24,5 +24,4 @@ var J3w1Pagination = class extends J3w1Element { }); } }; -//#endregion export { J3w1Pagination }; diff --git a/packages/ui/dist/copy/pagination/runtime/register/pagination.js b/packages/ui/dist/copy/pagination/runtime/register/pagination.js index 26680a048..113f449c2 100644 --- a/packages/ui/dist/copy/pagination/runtime/register/pagination.js +++ b/packages/ui/dist/copy/pagination/runtime/register/pagination.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Pagination } from "../components/pagination.js"; -//#region .cache/ui-build/entries/register/pagination.js +// .cache/ui-build/entries/register/pagination.js var element = registerElement("j3w1-pagination", J3w1Pagination); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/popover/manifest.json b/packages/ui/dist/copy/popover/manifest.json index bce25c327..3aa832e07 100644 --- a/packages/ui/dist/copy/popover/manifest.json +++ b/packages/ui/dist/copy/popover/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/popover.md", "dependencies": [ "register/popover.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/popover.js", - "chunks/overlays-BwgpF4jI.js" + "chunks/overlays-BW66WXLm.js" ], "files": { - "runtime/register/popover.js": "sha256-NDvrOkPFLsVu6H7xsvbIrVzEyB991xTSx7kQeyplwJo=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/popover.js": "sha256-JHzjjn0Oz3mo6v5yPi+1LrMA+ii8LIIozp+09bAkaIs=", - "runtime/chunks/overlays-BwgpF4jI.js": "sha256-NAd99OT4kDsFp8IHscKRus2jY6XRsq+GMzplWbJsY4U=", + "runtime/register/popover.js": "sha256-xRkCFvW2ZZFE7oiyzjI0LU04ybC1vn0qsZSMwBHa0W4=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/popover.js": "sha256-AKogsKXEGlZ2TM7DbJBqt95rmp+cUmED/ovBHzwqPBA=", + "runtime/chunks/overlays-BW66WXLm.js": "sha256-Z9etmUpuDuykKbJkriLMz8iiYnOP9uMUAshKwoHc1I8=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-xmMasEZmjEVePt3EbtGTGv48RqUg6XWxZKYkmzUQlQY=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/popover/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/popover/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/popover/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/popover/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/popover/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/popover/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/popover/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/popover/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/popover/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/popover/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/popover/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/popover/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/popover/runtime/chunks/overlays-BW66WXLm.js b/packages/ui/dist/copy/popover/runtime/chunks/overlays-BW66WXLm.js new file mode 100644 index 000000000..d05c73b46 --- /dev/null +++ b/packages/ui/dist/copy/popover/runtime/chunks/overlays-BW66WXLm.js @@ -0,0 +1,244 @@ +import { d as place, i as all, o as enabled, s as identify } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/overlays.js +function modal(root, { on }) { + const dialog = root.querySelector("dialog"); + if (!dialog) return {}; + let opener = null; + const show = (trigger = root.ownerDocument.activeElement) => { + if (dialog.open || root.hasAttribute("disabled")) return; + opener = trigger; + dialog.showModal(); + (dialog.querySelector("[autofocus]") ?? dialog.querySelector("button:not(.dialog-button-destructive)"))?.focus(); + root.emit("open", {}); + }; + const close = (value = "") => { + if (dialog.open) dialog.close(String(value)); + }; + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (button?.matches("[data-open]")) { + show(button); + return; + } + if (button && dialog.contains(button) && enabled(button)) { + if (button.matches("[data-close],.dialog-close,.drawer-close")) close(button.dataset.close ?? "cancel"); + else if (button.dataset.action && root.emit("action", { action: button.dataset.action })) close(button.dataset.action); + } + if (root.constructor.componentId === "drawer" && event.target.closest("a[href]") && dialog.contains(event.target)) close("navigate"); + }); + on(dialog, "cancel", (event) => { + if (!root.emit("cancel", {})) event.preventDefault(); + }); + on(dialog, "close", () => { + if (opener?.isConnected) opener.focus(); + root.emit("close", { returnValue: dialog.returnValue }); + }); + return { + show, + close, + get open() { + return dialog.open; + }, + set open(value) { + value ? show() : close(); + }, + get returnValue() { + return dialog.returnValue; + }, + cleanup() { + if (dialog.open) dialog.close(); + } + }; +} +function tooltip(root, { on }) { + const trigger = root.querySelector(".tooltip-trigger"), popup = root.querySelector("[role=\"tooltip\"]"); + if (!trigger || !popup) return {}; + identify(root, popup, "tooltip"); + trigger.setAttribute("aria-describedby", popup.id); + let timer, hideTimer, dismissed = false, hovering = false; + const stop = () => { + clearTimeout(timer); + clearTimeout(hideTimer); + }; + const hide = () => { + stop(); + popup.hidden = true; + }; + const show = () => { + stop(); + if (!dismissed) { + popup.hidden = false; + place(trigger, popup); + } + }; + const hideSoon = () => { + clearTimeout(timer); + clearTimeout(hideTimer); + hideTimer = setTimeout(() => { + if (!hovering && root.ownerDocument.activeElement !== trigger) hide(); + }, 300); + }; + on(trigger, "pointerenter", (event) => { + if (event.pointerType !== "touch") { + hovering = true; + dismissed = false; + clearTimeout(hideTimer); + if (popup.hidden) timer = setTimeout(show, 300); + } + }); + on(root, "pointerleave", (event) => { + if (!root.contains(event.relatedTarget)) { + hovering = false; + dismissed = false; + if (root.ownerDocument.activeElement !== trigger) hideSoon(); + } + }); + on(popup, "pointerenter", () => { + hovering = true; + stop(); + }); + on(trigger, "focus", () => { + dismissed = false; + show(); + }); + on(trigger, "blur", () => { + if (!hovering) hide(); + }); + on(trigger, "click", () => { + dismissed = true; + hide(); + }); + on(trigger, "pointerdown", (event) => { + if (event.pointerType === "touch") { + dismissed = false; + timer = setTimeout(show, 500); + } + }); + on(trigger, "pointerup", stop); + on(trigger, "pointercancel", stop); + on(root.ownerDocument, "keydown", (event) => { + if (event.key === "Escape" && !popup.hidden) { + event.preventDefault(); + event.stopImmediatePropagation(); + dismissed = true; + hide(); + } + }, { capture: true }); + on(root.ownerDocument, "scroll", () => { + if (!popup.hidden) place(trigger, popup); + }, { capture: true }); + on(root.ownerDocument.defaultView, "resize", () => { + if (!popup.hidden) place(trigger, popup); + }); + hide(); + return { + show, + hide, + get open() { + return !popup.hidden; + }, + cleanup: hide + }; +} +function popover(root, { on }) { + const trigger = root.querySelector("[data-popover-trigger]"), panel = root.querySelector("[data-popover-panel]"); + if (!trigger || !panel) return {}; + identify(root, panel, "popover"); + trigger.setAttribute("aria-controls", panel.id); + const native = typeof panel.showPopover === "function"; + if (native) { + panel.setAttribute("popover", "auto"); + panel.hidden = false; + } else panel.hidden = true; + let open = false; + const sync = (value) => { + open = value; + trigger.setAttribute("aria-expanded", String(value)); + root.emit("toggle", { expanded: value }); + }; + const show = () => { + if (open || !enabled(trigger)) return; + native ? panel.showPopover() : panel.hidden = false; + sync(true); + place(trigger, panel); + }; + const hide = (focus = false) => { + if (!open) return; + native ? panel.hidePopover() : panel.hidden = true; + sync(false); + if (focus) trigger.focus(); + }; + on(trigger, "click", () => open ? hide() : show()); + on(panel, "beforetoggle", (event) => { + open = event.newState === "open"; + trigger.setAttribute("aria-expanded", String(open)); + }); + on(panel, "click", (event) => { + if (event.target.closest("[data-close]")) hide(true); + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!native && !root.contains(event.target)) hide(); + }); + on(root, "keydown", (event) => { + if (event.key === "Escape" && open) { + event.preventDefault(); + event.stopPropagation(); + hide(true); + } + }); + on(root.ownerDocument.defaultView, "resize", () => { + if (open) place(trigger, panel); + }); + trigger.setAttribute("aria-expanded", "false"); + return { + show, + hide, + get open() { + return open; + }, + set open(value) { + value ? show() : hide(); + }, + cleanup() { + hide(); + } + }; +} +function feedback(root, { on }) { + const dismiss = (item) => { + if (!item || !root.emit("dismiss", { id: item.id })) return; + const hadFocus = item.contains(root.ownerDocument.activeElement); + const focusable = all(root.ownerDocument, "button,a[href],input,select,textarea,[tabindex='0']").filter((node) => enabled(node) && !node.closest("[hidden]")); + const currentIndex = focusable.indexOf(root.ownerDocument.activeElement); + const next = focusable.slice(currentIndex + 1).find((node) => !item.contains(node)) ?? focusable.slice(0, currentIndex).reverse().find((node) => !item.contains(node)); + item.hidden = true; + if (hadFocus) next?.focus(); + }; + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button)) return; + if (button.matches(".toast-close,.alert-close,.chip-remove,[data-dismiss]")) dismiss(button.closest(".toast,.alert,.chip") ?? root); + else if (button.matches(".chip-filter")) { + button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + root.emit("action", { + action: button.textContent.trim(), + pressed: button.getAttribute("aria-pressed") === "true" + }); + } else if (button.matches("[data-retry]")) root.emit("retry", {}); + else root.emit("action", { action: button.dataset.action ?? button.textContent.trim() }); + }); + on(root, "keydown", (event) => { + if (event.key === "Escape") { + const toast = event.target.closest(".toast"); + if (toast) { + event.preventDefault(); + event.stopPropagation(); + dismiss(toast); + } + } + }); + return { dismiss(id) { + dismiss(id ? root.querySelector(`#${CSS.escape(id)}`) : root.querySelector(".toast,.alert") ?? root); + } }; +} +export { tooltip as i, modal as n, popover as r, feedback as t }; diff --git a/packages/ui/dist/copy/popover/runtime/chunks/overlays-BwgpF4jI.js b/packages/ui/dist/copy/popover/runtime/chunks/overlays-BwgpF4jI.js deleted file mode 100644 index 4b8de2e8b..000000000 --- a/packages/ui/dist/copy/popover/runtime/chunks/overlays-BwgpF4jI.js +++ /dev/null @@ -1,245 +0,0 @@ -import { d as place, i as all, o as enabled, s as identify } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/overlays.js -function modal(root, { on }) { - const dialog = root.querySelector("dialog"); - if (!dialog) return {}; - let opener = null; - const show = (trigger = root.ownerDocument.activeElement) => { - if (dialog.open || root.hasAttribute("disabled")) return; - opener = trigger; - dialog.showModal(); - (dialog.querySelector("[autofocus]") ?? dialog.querySelector("button:not(.dialog-button-destructive)"))?.focus(); - root.emit("open", {}); - }; - const close = (value = "") => { - if (dialog.open) dialog.close(String(value)); - }; - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (button?.matches("[data-open]")) { - show(button); - return; - } - if (button && dialog.contains(button) && enabled(button)) { - if (button.matches("[data-close],.dialog-close,.drawer-close")) close(button.dataset.close ?? "cancel"); - else if (button.dataset.action && root.emit("action", { action: button.dataset.action })) close(button.dataset.action); - } - if (root.constructor.componentId === "drawer" && event.target.closest("a[href]") && dialog.contains(event.target)) close("navigate"); - }); - on(dialog, "cancel", (event) => { - if (!root.emit("cancel", {})) event.preventDefault(); - }); - on(dialog, "close", () => { - if (opener?.isConnected) opener.focus(); - root.emit("close", { returnValue: dialog.returnValue }); - }); - return { - show, - close, - get open() { - return dialog.open; - }, - set open(value) { - value ? show() : close(); - }, - get returnValue() { - return dialog.returnValue; - }, - cleanup() { - if (dialog.open) dialog.close(); - } - }; -} -function tooltip(root, { on }) { - const trigger = root.querySelector(".tooltip-trigger"), popup = root.querySelector("[role=\"tooltip\"]"); - if (!trigger || !popup) return {}; - identify(root, popup, "tooltip"); - trigger.setAttribute("aria-describedby", popup.id); - let timer, hideTimer, dismissed = false, hovering = false; - const stop = () => { - clearTimeout(timer); - clearTimeout(hideTimer); - }; - const hide = () => { - stop(); - popup.hidden = true; - }; - const show = () => { - stop(); - if (!dismissed) { - popup.hidden = false; - place(trigger, popup); - } - }; - const hideSoon = () => { - clearTimeout(timer); - clearTimeout(hideTimer); - hideTimer = setTimeout(() => { - if (!hovering && root.ownerDocument.activeElement !== trigger) hide(); - }, 300); - }; - on(trigger, "pointerenter", (event) => { - if (event.pointerType !== "touch") { - hovering = true; - dismissed = false; - clearTimeout(hideTimer); - if (popup.hidden) timer = setTimeout(show, 300); - } - }); - on(root, "pointerleave", (event) => { - if (!root.contains(event.relatedTarget)) { - hovering = false; - dismissed = false; - if (root.ownerDocument.activeElement !== trigger) hideSoon(); - } - }); - on(popup, "pointerenter", () => { - hovering = true; - stop(); - }); - on(trigger, "focus", () => { - dismissed = false; - show(); - }); - on(trigger, "blur", () => { - if (!hovering) hide(); - }); - on(trigger, "click", () => { - dismissed = true; - hide(); - }); - on(trigger, "pointerdown", (event) => { - if (event.pointerType === "touch") { - dismissed = false; - timer = setTimeout(show, 500); - } - }); - on(trigger, "pointerup", stop); - on(trigger, "pointercancel", stop); - on(root.ownerDocument, "keydown", (event) => { - if (event.key === "Escape" && !popup.hidden) { - event.preventDefault(); - event.stopImmediatePropagation(); - dismissed = true; - hide(); - } - }, { capture: true }); - on(root.ownerDocument, "scroll", () => { - if (!popup.hidden) place(trigger, popup); - }, { capture: true }); - on(root.ownerDocument.defaultView, "resize", () => { - if (!popup.hidden) place(trigger, popup); - }); - hide(); - return { - show, - hide, - get open() { - return !popup.hidden; - }, - cleanup: hide - }; -} -function popover(root, { on }) { - const trigger = root.querySelector("[data-popover-trigger]"), panel = root.querySelector("[data-popover-panel]"); - if (!trigger || !panel) return {}; - identify(root, panel, "popover"); - trigger.setAttribute("aria-controls", panel.id); - const native = typeof panel.showPopover === "function"; - if (native) { - panel.setAttribute("popover", "auto"); - panel.hidden = false; - } else panel.hidden = true; - let open = false; - const sync = (value) => { - open = value; - trigger.setAttribute("aria-expanded", String(value)); - root.emit("toggle", { expanded: value }); - }; - const show = () => { - if (open || !enabled(trigger)) return; - native ? panel.showPopover() : panel.hidden = false; - sync(true); - place(trigger, panel); - }; - const hide = (focus = false) => { - if (!open) return; - native ? panel.hidePopover() : panel.hidden = true; - sync(false); - if (focus) trigger.focus(); - }; - on(trigger, "click", () => open ? hide() : show()); - on(panel, "beforetoggle", (event) => { - open = event.newState === "open"; - trigger.setAttribute("aria-expanded", String(open)); - }); - on(panel, "click", (event) => { - if (event.target.closest("[data-close]")) hide(true); - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!native && !root.contains(event.target)) hide(); - }); - on(root, "keydown", (event) => { - if (event.key === "Escape" && open) { - event.preventDefault(); - event.stopPropagation(); - hide(true); - } - }); - on(root.ownerDocument.defaultView, "resize", () => { - if (open) place(trigger, panel); - }); - trigger.setAttribute("aria-expanded", "false"); - return { - show, - hide, - get open() { - return open; - }, - set open(value) { - value ? show() : hide(); - }, - cleanup() { - hide(); - } - }; -} -function feedback(root, { on }) { - const dismiss = (item) => { - if (!item || !root.emit("dismiss", { id: item.id })) return; - const hadFocus = item.contains(root.ownerDocument.activeElement); - const focusable = all(root.ownerDocument, "button,a[href],input,select,textarea,[tabindex='0']").filter((node) => enabled(node) && !node.closest("[hidden]")); - const currentIndex = focusable.indexOf(root.ownerDocument.activeElement); - const next = focusable.slice(currentIndex + 1).find((node) => !item.contains(node)) ?? focusable.slice(0, currentIndex).reverse().find((node) => !item.contains(node)); - item.hidden = true; - if (hadFocus) next?.focus(); - }; - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button)) return; - if (button.matches(".toast-close,.alert-close,.chip-remove,[data-dismiss]")) dismiss(button.closest(".toast,.alert,.chip") ?? root); - else if (button.matches(".chip-filter")) { - button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - root.emit("action", { - action: button.textContent.trim(), - pressed: button.getAttribute("aria-pressed") === "true" - }); - } else if (button.matches("[data-retry]")) root.emit("retry", {}); - else root.emit("action", { action: button.dataset.action ?? button.textContent.trim() }); - }); - on(root, "keydown", (event) => { - if (event.key === "Escape") { - const toast = event.target.closest(".toast"); - if (toast) { - event.preventDefault(); - event.stopPropagation(); - dismiss(toast); - } - } - }); - return { dismiss(id) { - dismiss(id ? root.querySelector(`#${CSS.escape(id)}`) : root.querySelector(".toast,.alert") ?? root); - } }; -} -//#endregion -export { tooltip as i, modal as n, popover as r, feedback as t }; diff --git a/packages/ui/dist/copy/popover/runtime/components/popover.js b/packages/ui/dist/copy/popover/runtime/components/popover.js index cd98bf9db..94c3eb15a 100644 --- a/packages/ui/dist/copy/popover/runtime/components/popover.js +++ b/packages/ui/dist/copy/popover/runtime/components/popover.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as popover } from "../chunks/overlays-BwgpF4jI.js"; -//#region .cache/ui-build/entries/components/popover.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as popover } from "../chunks/overlays-BW66WXLm.js"; +// .cache/ui-build/entries/components/popover.js var J3w1Popover = class extends J3w1Element { static componentId = "popover"; static version = "4.0.0"; - static implementationId = "sha256-544d7ON825LY8X5xEBzRzpHfZ1h2hjozJQ8CIUd0dwQ="; + static implementationId = "sha256-0lpdoNXcJ4OtvOncSedDRAZh8Qqu3IC+U2AFJbsDWgo="; static connect = popover; static upgradeProperties = [ "disabled", @@ -32,5 +32,4 @@ var J3w1Popover = class extends J3w1Element { }); } }; -//#endregion export { J3w1Popover }; diff --git a/packages/ui/dist/copy/popover/runtime/register/popover.js b/packages/ui/dist/copy/popover/runtime/register/popover.js index 5f801317f..48c7a5def 100644 --- a/packages/ui/dist/copy/popover/runtime/register/popover.js +++ b/packages/ui/dist/copy/popover/runtime/register/popover.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Popover } from "../components/popover.js"; -//#region .cache/ui-build/entries/register/popover.js +// .cache/ui-build/entries/register/popover.js var element = registerElement("j3w1-popover", J3w1Popover); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/progress/manifest.json b/packages/ui/dist/copy/progress/manifest.json index 997f555ab..27de7d1c8 100644 --- a/packages/ui/dist/copy/progress/manifest.json +++ b/packages/ui/dist/copy/progress/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/progress.md", "dependencies": [ "register/progress.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/progress.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/progress.js": "sha256-njMsMaNTGgxOBV8TIDHAQYyRI8+ERzh0jbkOW22fUzc=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/progress.js": "sha256-nQLxDlUaGyc+Y+OKp0jTGxlgHN79YT/NpaldZf1fxSY=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/progress.js": "sha256-544wDL2CKnD0+1v3NSxcLVzXp1+GIcKTRFrtYDC4bpE=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/progress.js": "sha256-ZEE/23ULhPm5c1MCkBDOl8/cfGhFjt3rCoBmtS07S4w=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-UwXFHO6OA2kZ3cHUZ8xWNx21ZB+espmS0o/GDj19Q4I=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/progress/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/progress/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/progress/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/progress/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/progress/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/progress/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/progress/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/progress/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/progress/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/progress/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/progress/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/progress/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/progress/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/progress/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/progress/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/progress/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/progress/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/progress/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/progress/runtime/components/progress.js b/packages/ui/dist/copy/progress/runtime/components/progress.js index c4664d716..ba0759904 100644 --- a/packages/ui/dist/copy/progress/runtime/components/progress.js +++ b/packages/ui/dist/copy/progress/runtime/components/progress.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/progress.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/progress.js var J3w1Progress = class extends J3w1Element { static componentId = "progress"; static version = "4.0.0"; - static implementationId = "sha256-ayNpjS/tJF/VzILGmci24aDE3GR3edKDd1sGAVN7HtQ="; + static implementationId = "sha256-akxgN48xfy+cHsPHoXeqwvAxIYp+yn0gTEmRWM0hWJE="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Progress }; diff --git a/packages/ui/dist/copy/progress/runtime/register/progress.js b/packages/ui/dist/copy/progress/runtime/register/progress.js index 29de54fb7..da67feba7 100644 --- a/packages/ui/dist/copy/progress/runtime/register/progress.js +++ b/packages/ui/dist/copy/progress/runtime/register/progress.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Progress } from "../components/progress.js"; -//#region .cache/ui-build/entries/register/progress.js +// .cache/ui-build/entries/register/progress.js var element = registerElement("j3w1-progress", J3w1Progress); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/radio-group/manifest.json b/packages/ui/dist/copy/radio-group/manifest.json index f2621ce3a..e719e6884 100644 --- a/packages/ui/dist/copy/radio-group/manifest.json +++ b/packages/ui/dist/copy/radio-group/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/radio-group.md", "dependencies": [ "register/radio-group.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/radio-group.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/radio-group.js": "sha256-ewlJRFup1XukqJJNHbI7o4+IBxMHYc4zRErGTSTTCOE=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/radio-group.js": "sha256-2H9k0HsCH7vOePvpZIurg4X8R/tWx69+wbMsKbawdJQ=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/radio-group.js": "sha256-zr8E48f84xnrzU/bENHN+06GlwRTImWeLSXQJM6JSYk=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/radio-group.js": "sha256-pTf7n/I+GJNCcHKGvEvK9JeW+47LLqnSqA0IMQvcFvg=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-YV0K4E9IvTApjrBK9vEmi8LtX8q3bUSlq810ysD4Kpk=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/radio-group/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/radio-group/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/radio-group/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/radio-group/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/radio-group/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/radio-group/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/radio-group/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/radio-group/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/radio-group/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/radio-group/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/radio-group/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/radio-group/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/radio-group/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/radio-group/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/radio-group/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/radio-group/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/radio-group/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/radio-group/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/radio-group/runtime/components/radio-group.js b/packages/ui/dist/copy/radio-group/runtime/components/radio-group.js index 9c5100135..eef0e2a61 100644 --- a/packages/ui/dist/copy/radio-group/runtime/components/radio-group.js +++ b/packages/ui/dist/copy/radio-group/runtime/components/radio-group.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/radio-group.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/radio-group.js var J3w1RadioGroup = class extends J3w1Element { static componentId = "radio-group"; static version = "4.0.0"; - static implementationId = "sha256-qoOHybVksZNlma+H614aGdgiZ/u0EegTSeDcIojBXA0="; + static implementationId = "sha256-k3eeoFy7itEt3SayQ+FY+DOTTb3EuUsTLSVncf4Pi7U="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1RadioGroup }; diff --git a/packages/ui/dist/copy/radio-group/runtime/register/radio-group.js b/packages/ui/dist/copy/radio-group/runtime/register/radio-group.js index a41f213ff..e27e5a281 100644 --- a/packages/ui/dist/copy/radio-group/runtime/register/radio-group.js +++ b/packages/ui/dist/copy/radio-group/runtime/register/radio-group.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1RadioGroup } from "../components/radio-group.js"; -//#region .cache/ui-build/entries/register/radio-group.js +// .cache/ui-build/entries/register/radio-group.js var element = registerElement("j3w1-radio-group", J3w1RadioGroup); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/range/manifest.json b/packages/ui/dist/copy/range/manifest.json index 1c3d50799..3f25438a7 100644 --- a/packages/ui/dist/copy/range/manifest.json +++ b/packages/ui/dist/copy/range/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/range.md", "dependencies": [ "register/range.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/range.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/range.js": "sha256-HYsfnS/M/wjcD+spw64Qas+a8kndWqTvSRdBedy0U6g=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/range.js": "sha256-UOtb5bcowunT33yEodiHV5YKGl/OTUl5qSsO3xxwSHY=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/range.js": "sha256-E1UD7e4zjan+J5sC3GAZQNpX32Zeu8iAb+A2KfuUO/w=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/range.js": "sha256-QRunxTcE2W9hO8fpbtB9TIPALr/yUFibuPV86LgLThI=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-4ayZ4hpLNMgckII249GLN4LXptEvABeXopUcVCG8gLc=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/range/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/range/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/range/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/range/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/range/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/range/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/range/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/range/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/range/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/range/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/range/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/range/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/range/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/range/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/range/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/range/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/range/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/range/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/range/runtime/components/range.js b/packages/ui/dist/copy/range/runtime/components/range.js index b560b2a51..9cf3b5c15 100644 --- a/packages/ui/dist/copy/range/runtime/components/range.js +++ b/packages/ui/dist/copy/range/runtime/components/range.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/range.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/range.js var J3w1Range = class extends J3w1Element { static componentId = "range"; static version = "4.0.0"; - static implementationId = "sha256-zCJuNTps0+QV29mUu6dGnyhnpifuS7WnpWWjLJtkpdo="; + static implementationId = "sha256-i6nR59cp/+WnCt0GMdESQTDAwvHuvPWB0oPhG86AZOs="; static connect = fields; static upgradeProperties = [ "disabled", @@ -27,5 +27,4 @@ var J3w1Range = class extends J3w1Element { return this._api.clear(...args); } }; -//#endregion export { J3w1Range }; diff --git a/packages/ui/dist/copy/range/runtime/register/range.js b/packages/ui/dist/copy/range/runtime/register/range.js index 63b83eab7..63fda2d7f 100644 --- a/packages/ui/dist/copy/range/runtime/register/range.js +++ b/packages/ui/dist/copy/range/runtime/register/range.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Range } from "../components/range.js"; -//#region .cache/ui-build/entries/register/range.js +// .cache/ui-build/entries/register/range.js var element = registerElement("j3w1-range", J3w1Range); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/repeater/manifest.json b/packages/ui/dist/copy/repeater/manifest.json index 61a82d823..38b073f82 100644 --- a/packages/ui/dist/copy/repeater/manifest.json +++ b/packages/ui/dist/copy/repeater/manifest.json @@ -5,19 +5,19 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/repeater.md", "dependencies": [ "register/repeater.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/repeater.js", - "chunks/advanced-CqBF0dSb.js", - "chunks/markup-DeQ4bEMR.js" + "chunks/advanced-BrFnVc0y.js", + "chunks/markup-AopKpwOF.js" ], "files": { - "runtime/register/repeater.js": "sha256-+BJGwFC4ULsZj2rUXucqIP4bkN1LZVFvuFrN1eK5zsw=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/repeater.js": "sha256-S5GJEE4PdeXjexdZXmIgJnjsOURVZHpQCSJzc+huJXc=", - "runtime/chunks/advanced-CqBF0dSb.js": "sha256-ozOzkRU6IeVGBqU3XQ0aLledkAi9vcs8dJdMQutVevs=", - "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", + "runtime/register/repeater.js": "sha256-eOxh9asjFElUMBptJubnb4sagYVPb5+yydspzDqugOE=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/repeater.js": "sha256-FOveMEI56LVJDMyXlEMbXGE9D0/LX85DQ9meCqa8G74=", + "runtime/chunks/advanced-BrFnVc0y.js": "sha256-FVberBpKO49P/WGnxa61BTxhYsLnnvMFInur/TwjG44=", + "runtime/chunks/markup-AopKpwOF.js": "sha256-/Dn3cWEmlRQzeQAPVf+C0AooVb1pdIQeNeqd1fQVoPc=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-rx26lMPjdf1Z/n5dSt0W680aeH4/Vf/JHj+aVD7Yd0g=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/repeater/runtime/chunks/advanced-BrFnVc0y.js b/packages/ui/dist/copy/repeater/runtime/chunks/advanced-BrFnVc0y.js new file mode 100644 index 000000000..36e7638c4 --- /dev/null +++ b/packages/ui/dist/copy/repeater/runtime/chunks/advanced-BrFnVc0y.js @@ -0,0 +1,344 @@ +import { c as keyIndex, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-DqwWT5pJ.js"; +import { t as IDREFS } from "./markup-AopKpwOF.js"; +// packages/ui/src/behaviors/advanced.js +function tree(root, { on }) { + const treeRoot = root.querySelector("[role=\"tree\"]"); + if (!treeRoot) return {}; + const items = () => all(treeRoot, "[role=\"treeitem\"]"); + const shown = () => items().filter(visible); + const group = (item) => [...item.children].find((node) => node.getAttribute("role") === "group"); + const parent = (item) => item.parentElement.closest("[role=\"treeitem\"]"); + items().forEach((item, index) => { + identify(root, item, `node-${index}`); + const children = group(item); + if (children) { + if (!item.hasAttribute("aria-expanded")) item.setAttribute("aria-expanded", "false"); + children.hidden = item.getAttribute("aria-expanded") !== "true"; + } + }); + const select = (id) => { + const item = items().find((node) => node.id === id); + if (!item || !enabled(item)) throw new RangeError(`Unknown enabled tree item: ${id}`); + items().forEach((node) => node.setAttribute("aria-selected", String(node === item))); + }; + const expand = (id, expanded = true) => { + const item = items().find((node) => node.id === id), children = item && group(item); + if (!children) throw new RangeError(`Unknown tree parent: ${id}`); + if (!expanded && children.contains(root.ownerDocument.activeElement)) rove(items(), items().indexOf(item)); + item.setAttribute("aria-expanded", String(Boolean(expanded))); + children.hidden = !expanded; + const toggle = item.querySelector(":scope > [data-tree-label] > [data-tree-toggle]"); + if (toggle) toggle.setAttribute("aria-label", expanded ? "Collapse" : "Expand"); + root.emit("toggle", { + id, + expanded: Boolean(expanded) + }); + }; + const activate = (item) => { + if (enabled(item)) { + select(item.id); + root.emit("select", { id: item.id }); + } + }; + const initial = shown(); + rove(initial, Math.max(0, initial.findIndex((item) => item.tabIndex === 0)), false); + on(treeRoot, "click", (event) => { + const item = event.target.closest("[role=\"treeitem\"]"); + if (!item) return; + rove(shown(), shown().indexOf(item)); + if (event.target.closest("[data-tree-toggle]") && group(item)) expand(item.id, item.getAttribute("aria-expanded") !== "true"); + else activate(item); + }); + on(treeRoot, "dblclick", (event) => { + const item = event.target.closest("[role=\"treeitem\"]"); + if (item && group(item) && !event.target.closest("[data-tree-toggle]")) expand(item.id, item.getAttribute("aria-expanded") !== "true"); + }); + on(treeRoot, "keydown", (event) => { + const item = event.target.closest("[role=\"treeitem\"]"); + if (!item) return; + const options = shown(), index = options.indexOf(item), rtl = getComputedStyle(treeRoot).direction === "rtl"; + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const next = keyIndex({ + key: event.key, + index, + length: options.length, + wrap: false + }); + rove(options, next); + } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight")) { + event.preventDefault(); + if (group(item)) { + if (item.getAttribute("aria-expanded") !== "true") expand(item.id); + else rove(shown(), shown().indexOf(item) + 1); + } + } else if (event.key === (rtl ? "ArrowRight" : "ArrowLeft")) { + event.preventDefault(); + if (group(item) && item.getAttribute("aria-expanded") === "true") expand(item.id, false); + else if (parent(item)) rove(options, options.indexOf(parent(item))); + } else if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + activate(item); + } else if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(":scope > [data-tree-label]")?.textContent ?? node.firstChild?.textContent ?? "").trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); + if (found) { + event.preventDefault(); + rove(options, options.indexOf(found)); + } + } + }); + return { + expand, + get selectedId() { + return items().find((item) => item.getAttribute("aria-selected") === "true")?.id ?? ""; + }, + set selectedId(id) { + select(id); + } + }; +} +function multiselect(root, { on, signal }) { + const query = root.querySelector("[data-filter]"), status = root.querySelector("[data-selection-status]"), boxes = all(root, "input[type=\"checkbox\"]"); + const values = () => boxes.filter((box) => box.checked).map((box) => box.value); + const draw = () => { + let matches = 0; + for (const box of boxes) { + const label = box.closest("label"); + if (!label) continue; + label.hidden = !label.textContent.toLocaleLowerCase().includes((query?.value ?? "").toLocaleLowerCase()); + if (!label.hidden) matches++; + } + if (status) status.textContent = `${matches} matching options; ${values().length} selected`; + }; + const report = () => { + draw(); + root.emit("selection", { values: values() }); + }; + const setValues = (selected) => { + if (!Array.isArray(selected) || selected.some((value) => !boxes.some((box) => box.value === value))) throw new TypeError("values must contain known checkbox values"); + boxes.forEach((box) => { + box.checked = selected.includes(box.value); + }); + draw(); + }; + const clear = () => { + if (root.hasAttribute("disabled")) return; + boxes.filter(enabled).forEach((box) => { + if (box.checked) { + box.checked = false; + nativeInput(box); + nativeInput(box, "change"); + } + }); + report(); + }; + on(query, "input", draw); + on(query, "keydown", (event) => { + if (event.key === "Escape" && query.value) { + event.preventDefault(); + event.stopPropagation(); + query.value = ""; + draw(); + } + }); + on(root.querySelector("[data-clear-selection]"), "click", clear); + boxes.forEach((box) => on(box, "change", report)); + on(boxes[0]?.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + clear, + get values() { + return values(); + }, + set values(selected) { + setValues(selected); + } + }; +} +function repeater(root, { on }) { + const rows = root.querySelector("[data-rows]"), template = root.querySelector("template[data-row-template]"), addButton = root.querySelector("[data-add]"), status = root.querySelector("[data-repeater-status]"); + if (!rows || !template) return {}; + let sequence = Number(root.dataset.rowSequence ?? 0); + const maximum = () => { + const value = Number(root.getAttribute("max") ?? 10); + if (!Number.isInteger(value) || value < 1 || value > 100) throw new RangeError("max must be an integer from 1 to 100"); + return value; + }; + const children = () => [...rows.children]; + const draw = (message) => { + const items = children(); + if (addButton) addButton.disabled = root.hasAttribute("disabled") || items.length >= maximum(); + const empty = root.querySelector("[data-empty]"); + if (empty) empty.hidden = items.length !== 0; + items.forEach((row, index) => { + all(row, "[data-move]").forEach((button) => { + button.disabled = root.hasAttribute("disabled") || (Number(button.dataset.move) < 0 ? index === 0 : index === items.length - 1); + }); + }); + if (message && status) status.textContent = message; + }; + const report = (message) => { + draw(message); + root.emit("rows", { ids: children().map((row) => row.id) }); + }; + const add = () => { + if (children().length >= maximum() || root.hasAttribute("disabled")) return null; + const row = template.content.firstElementChild.cloneNode(true); + const id = `${root.id}-row-${++sequence}`; + root.dataset.rowSequence = String(sequence); + row.id = id; + const ids = /* @__PURE__ */ new Map(); + all(row, "[id]").forEach((node) => { + ids.set(node.id, `${id}-${node.id}`); + node.id = ids.get(node.id); + }); + for (const node of all(row, "*")) for (const attr of [...node.attributes]) { + if (IDREFS.has(attr.name)) node.setAttribute(attr.name, attr.value.split(/\s+/).map((value) => ids.get(value) ?? value).join(" ")); + if (attr.name === "name") node.name = `${id}[${attr.value}]`; + } + rows.append(row); + report("Row added."); + row.querySelector("input,select,textarea,button")?.focus(); + return id; + }; + const remove = (id) => { + const items = children(), index = items.findIndex((row) => row.id === id); + if (index < 0) throw new RangeError(`Unknown row: ${id}`); + if (root.hasAttribute("disabled")) return; + const hadFocus = items[index].contains(root.ownerDocument.activeElement); + items[index].remove(); + report("Row removed."); + if (hadFocus) (children()[Math.min(index, children().length - 1)]?.querySelector("input,select,textarea,button") ?? addButton)?.focus(); + }; + const move = (id, direction) => { + if (![-1, 1].includes(direction)) throw new RangeError("direction must be -1 or 1"); + const items = children(), index = items.findIndex((row) => row.id === id), target = index + direction; + if (index < 0) throw new RangeError(`Unknown row: ${id}`); + if (target < 0 || target >= items.length || root.hasAttribute("disabled")) return; + const focused = root.ownerDocument.activeElement; + if (direction < 0) rows.insertBefore(items[index], items[target]); + else rows.insertBefore(items[target], items[index]); + report(direction < 0 ? "Row moved up." : "Row moved down."); + if (items[index].contains(focused) && !focused.disabled) focused.focus(); + else items[index].querySelector("input,select,textarea,button:not(:disabled)")?.focus(); + }; + on(addButton, "click", add); + on(rows, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button)) return; + const row = children().find((item) => item.contains(button)); + if (button.hasAttribute("data-remove")) remove(row.id); + else if (button.hasAttribute("data-move")) move(row.id, Number(button.dataset.move)); + }); + draw(); + return { + add, + remove, + move, + get rowIds() { + return children().map((row) => row.id); + }, + attributeChanged() { + draw(); + } + }; +} +function commandPalette(root, { on }) { + const dialog = root.querySelector("dialog"), input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"), status = root.querySelector("[data-command-status]"); + if (!dialog || !input || !list) return {}; + let opener, active = null; + all(list, "[role=\"option\"]").forEach((option, index) => { + identify(root, option, `command-${index}`); + option.tabIndex = -1; + }); + const options = () => all(list, "[role=\"option\"]").filter((option) => enabled(option) && !option.hidden); + const select = (option) => { + active = option; + all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); + if (option) { + input.setAttribute("aria-activedescendant", option.id); + option.scrollIntoView({ block: "nearest" }); + } else input.removeAttribute("aria-activedescendant"); + }; + const filter = () => { + all(list, "[role=\"option\"]").forEach((option) => { + option.hidden = !option.textContent.toLocaleLowerCase().includes(input.value.toLocaleLowerCase()); + }); + select(options()[0] ?? null); + if (status) status.textContent = `${options().length} commands`; + }; + const show = (trigger = root.ownerDocument.activeElement) => { + if (dialog.open || root.hasAttribute("disabled")) return; + opener = trigger; + dialog.showModal(); + filter(); + input.focus(); + }; + const close = () => { + if (dialog.open) dialog.close(); + }; + const invoke = (option) => { + if (!option || !enabled(option)) return; + const link = option.matches("a[href]") ? option : option.querySelector("a[href]"); + const proceed = root.emit("command", { + action: option.dataset.action ?? option.id, + href: link?.getAttribute("href") ?? null + }); + close(); + if (proceed && link) root.ownerDocument.defaultView.location.assign(link.href); + }; + on(root, "click", (event) => { + const trigger = event.target.closest("[data-open]"); + if (trigger) show(trigger); + else if (event.target.closest("[data-close]")) close(); + else { + const option = event.target.closest("[role=\"option\"]"); + if (option) { + event.preventDefault(); + invoke(option); + } + } + }); + on(input, "input", filter); + on(input, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + close(); + } else if (["ArrowDown", "ArrowUp"].includes(event.key)) { + event.preventDefault(); + const items = options(), index = items.indexOf(active); + if (items.length) select(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); + } else if (event.key === "Enter") { + event.preventDefault(); + invoke(active); + } + }); + on(dialog, "close", () => { + if (opener?.isConnected) opener.focus(); + }); + on(root.ownerDocument, "keydown", (event) => { + if (root.hasAttribute("shortcut") && (event.ctrlKey || event.metaKey) && !event.altKey && event.key.toLowerCase() === "k" && !event.defaultPrevented) { + event.preventDefault(); + dialog.open ? close() : show(); + } + }); + return { + show, + close, + get open() { + return dialog.open; + }, + set open(value) { + value ? show() : close(); + }, + cleanup: close + }; +} +export { tree as i, multiselect as n, repeater as r, commandPalette as t }; diff --git a/packages/ui/dist/copy/repeater/runtime/chunks/advanced-CqBF0dSb.js b/packages/ui/dist/copy/repeater/runtime/chunks/advanced-CqBF0dSb.js deleted file mode 100644 index 4a5c45981..000000000 --- a/packages/ui/dist/copy/repeater/runtime/chunks/advanced-CqBF0dSb.js +++ /dev/null @@ -1,345 +0,0 @@ -import { c as keyIndex, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-B7mo5Eq3.js"; -import { t as IDREFS } from "./markup-DeQ4bEMR.js"; -//#region packages/ui/src/behaviors/advanced.js -function tree(root, { on }) { - const treeRoot = root.querySelector("[role=\"tree\"]"); - if (!treeRoot) return {}; - const items = () => all(treeRoot, "[role=\"treeitem\"]"); - const shown = () => items().filter(visible); - const group = (item) => [...item.children].find((node) => node.getAttribute("role") === "group"); - const parent = (item) => item.parentElement.closest("[role=\"treeitem\"]"); - items().forEach((item, index) => { - identify(root, item, `node-${index}`); - const children = group(item); - if (children) { - if (!item.hasAttribute("aria-expanded")) item.setAttribute("aria-expanded", "false"); - children.hidden = item.getAttribute("aria-expanded") !== "true"; - } - }); - const select = (id) => { - const item = items().find((node) => node.id === id); - if (!item || !enabled(item)) throw new RangeError(`Unknown enabled tree item: ${id}`); - items().forEach((node) => node.setAttribute("aria-selected", String(node === item))); - }; - const expand = (id, expanded = true) => { - const item = items().find((node) => node.id === id), children = item && group(item); - if (!children) throw new RangeError(`Unknown tree parent: ${id}`); - if (!expanded && children.contains(root.ownerDocument.activeElement)) rove(items(), items().indexOf(item)); - item.setAttribute("aria-expanded", String(Boolean(expanded))); - children.hidden = !expanded; - const toggle = item.querySelector(":scope > [data-tree-label] > [data-tree-toggle]"); - if (toggle) toggle.setAttribute("aria-label", expanded ? "Collapse" : "Expand"); - root.emit("toggle", { - id, - expanded: Boolean(expanded) - }); - }; - const activate = (item) => { - if (enabled(item)) { - select(item.id); - root.emit("select", { id: item.id }); - } - }; - const initial = shown(); - rove(initial, Math.max(0, initial.findIndex((item) => item.tabIndex === 0)), false); - on(treeRoot, "click", (event) => { - const item = event.target.closest("[role=\"treeitem\"]"); - if (!item) return; - rove(shown(), shown().indexOf(item)); - if (event.target.closest("[data-tree-toggle]") && group(item)) expand(item.id, item.getAttribute("aria-expanded") !== "true"); - else activate(item); - }); - on(treeRoot, "dblclick", (event) => { - const item = event.target.closest("[role=\"treeitem\"]"); - if (item && group(item) && !event.target.closest("[data-tree-toggle]")) expand(item.id, item.getAttribute("aria-expanded") !== "true"); - }); - on(treeRoot, "keydown", (event) => { - const item = event.target.closest("[role=\"treeitem\"]"); - if (!item) return; - const options = shown(), index = options.indexOf(item), rtl = getComputedStyle(treeRoot).direction === "rtl"; - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const next = keyIndex({ - key: event.key, - index, - length: options.length, - wrap: false - }); - rove(options, next); - } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight")) { - event.preventDefault(); - if (group(item)) { - if (item.getAttribute("aria-expanded") !== "true") expand(item.id); - else rove(shown(), shown().indexOf(item) + 1); - } - } else if (event.key === (rtl ? "ArrowRight" : "ArrowLeft")) { - event.preventDefault(); - if (group(item) && item.getAttribute("aria-expanded") === "true") expand(item.id, false); - else if (parent(item)) rove(options, options.indexOf(parent(item))); - } else if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - activate(item); - } else if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(":scope > [data-tree-label]")?.textContent ?? node.firstChild?.textContent ?? "").trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); - if (found) { - event.preventDefault(); - rove(options, options.indexOf(found)); - } - } - }); - return { - expand, - get selectedId() { - return items().find((item) => item.getAttribute("aria-selected") === "true")?.id ?? ""; - }, - set selectedId(id) { - select(id); - } - }; -} -function multiselect(root, { on, signal }) { - const query = root.querySelector("[data-filter]"), status = root.querySelector("[data-selection-status]"), boxes = all(root, "input[type=\"checkbox\"]"); - const values = () => boxes.filter((box) => box.checked).map((box) => box.value); - const draw = () => { - let matches = 0; - for (const box of boxes) { - const label = box.closest("label"); - if (!label) continue; - label.hidden = !label.textContent.toLocaleLowerCase().includes((query?.value ?? "").toLocaleLowerCase()); - if (!label.hidden) matches++; - } - if (status) status.textContent = `${matches} matching options; ${values().length} selected`; - }; - const report = () => { - draw(); - root.emit("selection", { values: values() }); - }; - const setValues = (selected) => { - if (!Array.isArray(selected) || selected.some((value) => !boxes.some((box) => box.value === value))) throw new TypeError("values must contain known checkbox values"); - boxes.forEach((box) => { - box.checked = selected.includes(box.value); - }); - draw(); - }; - const clear = () => { - if (root.hasAttribute("disabled")) return; - boxes.filter(enabled).forEach((box) => { - if (box.checked) { - box.checked = false; - nativeInput(box); - nativeInput(box, "change"); - } - }); - report(); - }; - on(query, "input", draw); - on(query, "keydown", (event) => { - if (event.key === "Escape" && query.value) { - event.preventDefault(); - event.stopPropagation(); - query.value = ""; - draw(); - } - }); - on(root.querySelector("[data-clear-selection]"), "click", clear); - boxes.forEach((box) => on(box, "change", report)); - on(boxes[0]?.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - clear, - get values() { - return values(); - }, - set values(selected) { - setValues(selected); - } - }; -} -function repeater(root, { on }) { - const rows = root.querySelector("[data-rows]"), template = root.querySelector("template[data-row-template]"), addButton = root.querySelector("[data-add]"), status = root.querySelector("[data-repeater-status]"); - if (!rows || !template) return {}; - let sequence = Number(root.dataset.rowSequence ?? 0); - const maximum = () => { - const value = Number(root.getAttribute("max") ?? 10); - if (!Number.isInteger(value) || value < 1 || value > 100) throw new RangeError("max must be an integer from 1 to 100"); - return value; - }; - const children = () => [...rows.children]; - const draw = (message) => { - const items = children(); - if (addButton) addButton.disabled = root.hasAttribute("disabled") || items.length >= maximum(); - const empty = root.querySelector("[data-empty]"); - if (empty) empty.hidden = items.length !== 0; - items.forEach((row, index) => { - all(row, "[data-move]").forEach((button) => { - button.disabled = root.hasAttribute("disabled") || (Number(button.dataset.move) < 0 ? index === 0 : index === items.length - 1); - }); - }); - if (message && status) status.textContent = message; - }; - const report = (message) => { - draw(message); - root.emit("rows", { ids: children().map((row) => row.id) }); - }; - const add = () => { - if (children().length >= maximum() || root.hasAttribute("disabled")) return null; - const row = template.content.firstElementChild.cloneNode(true); - const id = `${root.id}-row-${++sequence}`; - root.dataset.rowSequence = String(sequence); - row.id = id; - const ids = /* @__PURE__ */ new Map(); - all(row, "[id]").forEach((node) => { - ids.set(node.id, `${id}-${node.id}`); - node.id = ids.get(node.id); - }); - for (const node of all(row, "*")) for (const attr of [...node.attributes]) { - if (IDREFS.has(attr.name)) node.setAttribute(attr.name, attr.value.split(/\s+/).map((value) => ids.get(value) ?? value).join(" ")); - if (attr.name === "name") node.name = `${id}[${attr.value}]`; - } - rows.append(row); - report("Row added."); - row.querySelector("input,select,textarea,button")?.focus(); - return id; - }; - const remove = (id) => { - const items = children(), index = items.findIndex((row) => row.id === id); - if (index < 0) throw new RangeError(`Unknown row: ${id}`); - if (root.hasAttribute("disabled")) return; - const hadFocus = items[index].contains(root.ownerDocument.activeElement); - items[index].remove(); - report("Row removed."); - if (hadFocus) (children()[Math.min(index, children().length - 1)]?.querySelector("input,select,textarea,button") ?? addButton)?.focus(); - }; - const move = (id, direction) => { - if (![-1, 1].includes(direction)) throw new RangeError("direction must be -1 or 1"); - const items = children(), index = items.findIndex((row) => row.id === id), target = index + direction; - if (index < 0) throw new RangeError(`Unknown row: ${id}`); - if (target < 0 || target >= items.length || root.hasAttribute("disabled")) return; - const focused = root.ownerDocument.activeElement; - if (direction < 0) rows.insertBefore(items[index], items[target]); - else rows.insertBefore(items[target], items[index]); - report(direction < 0 ? "Row moved up." : "Row moved down."); - if (items[index].contains(focused) && !focused.disabled) focused.focus(); - else items[index].querySelector("input,select,textarea,button:not(:disabled)")?.focus(); - }; - on(addButton, "click", add); - on(rows, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button)) return; - const row = children().find((item) => item.contains(button)); - if (button.hasAttribute("data-remove")) remove(row.id); - else if (button.hasAttribute("data-move")) move(row.id, Number(button.dataset.move)); - }); - draw(); - return { - add, - remove, - move, - get rowIds() { - return children().map((row) => row.id); - }, - attributeChanged() { - draw(); - } - }; -} -function commandPalette(root, { on }) { - const dialog = root.querySelector("dialog"), input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"), status = root.querySelector("[data-command-status]"); - if (!dialog || !input || !list) return {}; - let opener, active = null; - all(list, "[role=\"option\"]").forEach((option, index) => { - identify(root, option, `command-${index}`); - option.tabIndex = -1; - }); - const options = () => all(list, "[role=\"option\"]").filter((option) => enabled(option) && !option.hidden); - const select = (option) => { - active = option; - all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); - if (option) { - input.setAttribute("aria-activedescendant", option.id); - option.scrollIntoView({ block: "nearest" }); - } else input.removeAttribute("aria-activedescendant"); - }; - const filter = () => { - all(list, "[role=\"option\"]").forEach((option) => { - option.hidden = !option.textContent.toLocaleLowerCase().includes(input.value.toLocaleLowerCase()); - }); - select(options()[0] ?? null); - if (status) status.textContent = `${options().length} commands`; - }; - const show = (trigger = root.ownerDocument.activeElement) => { - if (dialog.open || root.hasAttribute("disabled")) return; - opener = trigger; - dialog.showModal(); - filter(); - input.focus(); - }; - const close = () => { - if (dialog.open) dialog.close(); - }; - const invoke = (option) => { - if (!option || !enabled(option)) return; - const link = option.matches("a[href]") ? option : option.querySelector("a[href]"); - const proceed = root.emit("command", { - action: option.dataset.action ?? option.id, - href: link?.getAttribute("href") ?? null - }); - close(); - if (proceed && link) root.ownerDocument.defaultView.location.assign(link.href); - }; - on(root, "click", (event) => { - const trigger = event.target.closest("[data-open]"); - if (trigger) show(trigger); - else if (event.target.closest("[data-close]")) close(); - else { - const option = event.target.closest("[role=\"option\"]"); - if (option) { - event.preventDefault(); - invoke(option); - } - } - }); - on(input, "input", filter); - on(input, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - close(); - } else if (["ArrowDown", "ArrowUp"].includes(event.key)) { - event.preventDefault(); - const items = options(), index = items.indexOf(active); - if (items.length) select(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); - } else if (event.key === "Enter") { - event.preventDefault(); - invoke(active); - } - }); - on(dialog, "close", () => { - if (opener?.isConnected) opener.focus(); - }); - on(root.ownerDocument, "keydown", (event) => { - if (root.hasAttribute("shortcut") && (event.ctrlKey || event.metaKey) && !event.altKey && event.key.toLowerCase() === "k" && !event.defaultPrevented) { - event.preventDefault(); - dialog.open ? close() : show(); - } - }); - return { - show, - close, - get open() { - return dialog.open; - }, - set open(value) { - value ? show() : close(); - }, - cleanup: close - }; -} -//#endregion -export { tree as i, multiselect as n, repeater as r, commandPalette as t }; diff --git a/packages/ui/dist/copy/repeater/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/repeater/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/repeater/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/repeater/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/repeater/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/repeater/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/repeater/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/repeater/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/repeater/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/repeater/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/repeater/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/repeater/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/repeater/runtime/chunks/markup-AopKpwOF.js b/packages/ui/dist/copy/repeater/runtime/chunks/markup-AopKpwOF.js new file mode 100644 index 000000000..bc1c52c0b --- /dev/null +++ b/packages/ui/dist/copy/repeater/runtime/chunks/markup-AopKpwOF.js @@ -0,0 +1,53 @@ +// scripts/lib/markup.mjs +var IDREFS = /* @__PURE__ */ new Set([ + "for", + "form", + "list", + "aria-labelledby", + "aria-describedby", + "aria-controls", + "aria-owns", + "aria-activedescendant", + "aria-details", + "aria-errormessage", + "headers" +]); +var walkMarkup = (node, visit) => { + visit(node); + for (const child of node.childNodes ?? []) walkMarkup(child, visit); + if (node.tagName === "template" && node.content) walkMarkup(node.content, visit); +}; +var attribute = (node, name) => node.attrs?.find((a) => a.name === name)?.value; +var setAttribute = (node, name, value = "") => { + if (!node?.attrs) return; + const current = node.attrs.find((a) => a.name === name); + if (current) current.value = value; + else node.attrs.push({ + name, + value + }); +}; +var removeAttribute = (node, name) => { + if (node.attrs) node.attrs = node.attrs.filter((a) => a.name !== name); +}; +var hasClass = (node, name) => attribute(node, "class")?.split(/\s+/).includes(name) ?? false; +var namespaceMarkup = (tree, decorate, { strict = true, renameNames = false } = {}) => { + const ids = /* @__PURE__ */ new Map(); + walkMarkup(tree, (node) => { + const id = attribute(node, "id"); + if (id === void 0) return; + if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(id) || ids.has(id)) throw new Error(`Invalid or duplicate markup ID: ${id}`); + ids.set(id, decorate(id)); + }); + const reference = (id) => { + if (!ids.has(id) && strict) throw new Error(`Unresolved markup ID reference: ${id}`); + return ids.get(id) ?? decorate(id); + }; + walkMarkup(tree, (node) => { + for (const attr of node.attrs ?? []) if (attr.name === "id") attr.value = reference(attr.value); + else if (IDREFS.has(attr.name)) attr.value = attr.value.trim().split(/\s+/).map(reference).join(" "); + else if (attr.name === "href" && attr.value.startsWith("#")) attr.value = `#${reference(attr.value.slice(1))}`; + else if (renameNames && attr.name === "name") attr.value = decorate(attr.value); + }); +}; +export { setAttribute as a, removeAttribute as i, hasClass as n, walkMarkup as o, namespaceMarkup as r, IDREFS as t }; diff --git a/packages/ui/dist/copy/repeater/runtime/chunks/markup-DeQ4bEMR.js b/packages/ui/dist/copy/repeater/runtime/chunks/markup-DeQ4bEMR.js deleted file mode 100644 index 77bd9471d..000000000 --- a/packages/ui/dist/copy/repeater/runtime/chunks/markup-DeQ4bEMR.js +++ /dev/null @@ -1,54 +0,0 @@ -//#region scripts/lib/markup.mjs -var IDREFS = /* @__PURE__ */ new Set([ - "for", - "form", - "list", - "aria-labelledby", - "aria-describedby", - "aria-controls", - "aria-owns", - "aria-activedescendant", - "aria-details", - "aria-errormessage", - "headers" -]); -var walkMarkup = (node, visit) => { - visit(node); - for (const child of node.childNodes ?? []) walkMarkup(child, visit); - if (node.tagName === "template" && node.content) walkMarkup(node.content, visit); -}; -var attribute = (node, name) => node.attrs?.find((a) => a.name === name)?.value; -var setAttribute = (node, name, value = "") => { - if (!node?.attrs) return; - const current = node.attrs.find((a) => a.name === name); - if (current) current.value = value; - else node.attrs.push({ - name, - value - }); -}; -var removeAttribute = (node, name) => { - if (node.attrs) node.attrs = node.attrs.filter((a) => a.name !== name); -}; -var hasClass = (node, name) => attribute(node, "class")?.split(/\s+/).includes(name) ?? false; -var namespaceMarkup = (tree, decorate, { strict = true, renameNames = false } = {}) => { - const ids = /* @__PURE__ */ new Map(); - walkMarkup(tree, (node) => { - const id = attribute(node, "id"); - if (id === void 0) return; - if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(id) || ids.has(id)) throw new Error(`Invalid or duplicate markup ID: ${id}`); - ids.set(id, decorate(id)); - }); - const reference = (id) => { - if (!ids.has(id) && strict) throw new Error(`Unresolved markup ID reference: ${id}`); - return ids.get(id) ?? decorate(id); - }; - walkMarkup(tree, (node) => { - for (const attr of node.attrs ?? []) if (attr.name === "id") attr.value = reference(attr.value); - else if (IDREFS.has(attr.name)) attr.value = attr.value.trim().split(/\s+/).map(reference).join(" "); - else if (attr.name === "href" && attr.value.startsWith("#")) attr.value = `#${reference(attr.value.slice(1))}`; - else if (renameNames && attr.name === "name") attr.value = decorate(attr.value); - }); -}; -//#endregion -export { setAttribute as a, removeAttribute as i, hasClass as n, walkMarkup as o, namespaceMarkup as r, IDREFS as t }; diff --git a/packages/ui/dist/copy/repeater/runtime/components/repeater.js b/packages/ui/dist/copy/repeater/runtime/components/repeater.js index 0874370f2..e1c1bb988 100644 --- a/packages/ui/dist/copy/repeater/runtime/components/repeater.js +++ b/packages/ui/dist/copy/repeater/runtime/components/repeater.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as repeater } from "../chunks/advanced-CqBF0dSb.js"; -//#region .cache/ui-build/entries/components/repeater.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as repeater } from "../chunks/advanced-BrFnVc0y.js"; +// .cache/ui-build/entries/components/repeater.js var J3w1Repeater = class extends J3w1Element { static componentId = "repeater"; static version = "4.0.0"; - static implementationId = "sha256-G3uVYtEsLo70OmMPhofMD2YylFEq1kezRvUEMrNnRII="; + static implementationId = "sha256-w4XS7/LW7dUC4L/+YrgFuI+YMBos9KBQBiuK80Uns6g="; static connect = repeater; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...[ @@ -28,5 +28,4 @@ var J3w1Repeater = class extends J3w1Element { return this._api?.rowIds; } }; -//#endregion export { J3w1Repeater }; diff --git a/packages/ui/dist/copy/repeater/runtime/register/repeater.js b/packages/ui/dist/copy/repeater/runtime/register/repeater.js index 6565442ff..eb4811308 100644 --- a/packages/ui/dist/copy/repeater/runtime/register/repeater.js +++ b/packages/ui/dist/copy/repeater/runtime/register/repeater.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Repeater } from "../components/repeater.js"; -//#region .cache/ui-build/entries/register/repeater.js +// .cache/ui-build/entries/register/repeater.js var element = registerElement("j3w1-repeater", J3w1Repeater); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/search-field/manifest.json b/packages/ui/dist/copy/search-field/manifest.json index e696d3d8c..bc42559e8 100644 --- a/packages/ui/dist/copy/search-field/manifest.json +++ b/packages/ui/dist/copy/search-field/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/search-field.md", "dependencies": [ "register/search-field.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/search-field.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/search-field.js": "sha256-oIExIQ80Xzt1d5Y8KclVl+lAi+cgOMhKMFNPBz8fEXY=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/search-field.js": "sha256-HCnoLO1ZZvDEqeON+Ir7Q+XChuArNr/tJ7H+lnVTJPw=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/search-field.js": "sha256-6LYU8HU+rH1uC262cp+QTcMOL1fOJadTf2sVIOar7yw=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/search-field.js": "sha256-DR2wccoQwBDsamOMrOnUSaYWdhk+1zRdrnB9VfaIthY=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-wwF2mPKTtvrFcPXYn8OoWoeJPj5KgkmPbjay/kNVq6s=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/search-field/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/search-field/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/search-field/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/search-field/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/search-field/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/search-field/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/search-field/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/search-field/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/search-field/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/search-field/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/search-field/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/search-field/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/search-field/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/search-field/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/search-field/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/search-field/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/search-field/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/search-field/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/search-field/runtime/components/search-field.js b/packages/ui/dist/copy/search-field/runtime/components/search-field.js index 666ca6dde..89b2baea5 100644 --- a/packages/ui/dist/copy/search-field/runtime/components/search-field.js +++ b/packages/ui/dist/copy/search-field/runtime/components/search-field.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/search-field.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/search-field.js var J3w1SearchField = class extends J3w1Element { static componentId = "search-field"; static version = "4.0.0"; - static implementationId = "sha256-nopARV2ViNiuyBqGv6KjxLJ3uaaVqRJ3K7Mgtg/mS7Q="; + static implementationId = "sha256-tI6csnLzo3YwSslahWEtsgW+3pvLdmXr4NI4noiRcxA="; static connect = fields; static upgradeProperties = [ "disabled", @@ -27,5 +27,4 @@ var J3w1SearchField = class extends J3w1Element { return this._api.clear(...args); } }; -//#endregion export { J3w1SearchField }; diff --git a/packages/ui/dist/copy/search-field/runtime/register/search-field.js b/packages/ui/dist/copy/search-field/runtime/register/search-field.js index 169a29a47..d30d137f6 100644 --- a/packages/ui/dist/copy/search-field/runtime/register/search-field.js +++ b/packages/ui/dist/copy/search-field/runtime/register/search-field.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1SearchField } from "../components/search-field.js"; -//#region .cache/ui-build/entries/register/search-field.js +// .cache/ui-build/entries/register/search-field.js var element = registerElement("j3w1-search-field", J3w1SearchField); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/segmented-control/manifest.json b/packages/ui/dist/copy/segmented-control/manifest.json index 68ccd7eb3..3b2bad2ab 100644 --- a/packages/ui/dist/copy/segmented-control/manifest.json +++ b/packages/ui/dist/copy/segmented-control/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/segmented-control.md", "dependencies": [ "register/segmented-control.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/segmented-control.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/segmented-control.js": "sha256-n6tsq/njNAYhqF4fvBMTvNQc+KRA4dsIBCmrUsrTA+U=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/segmented-control.js": "sha256-8hAeFwje9ZkB0c6k2tQrV2hjw4TCznTY3w0tOFD/egQ=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/segmented-control.js": "sha256-OeqnvpiM0P88F9H4q+eT555nEkKiMwf8ieOzeMnawzg=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/segmented-control.js": "sha256-hTlWptpOLy1sPlY00bm/exJfRnlx3Sxna0aJaoS41Ok=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-+okbI0q5jMbA3Dv/3pcbgQ3LJeXS73lSYOUnG9ki9UE=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/segmented-control/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/segmented-control/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/segmented-control/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/segmented-control/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/segmented-control/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/segmented-control/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/segmented-control/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/segmented-control/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/segmented-control/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/segmented-control/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/segmented-control/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/segmented-control/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/segmented-control/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/segmented-control/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/segmented-control/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/segmented-control/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/segmented-control/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/segmented-control/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/segmented-control/runtime/components/segmented-control.js b/packages/ui/dist/copy/segmented-control/runtime/components/segmented-control.js index 6ffc9b94e..722077482 100644 --- a/packages/ui/dist/copy/segmented-control/runtime/components/segmented-control.js +++ b/packages/ui/dist/copy/segmented-control/runtime/components/segmented-control.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/segmented-control.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/segmented-control.js var J3w1SegmentedControl = class extends J3w1Element { static componentId = "segmented-control"; static version = "4.0.0"; - static implementationId = "sha256-ULY50CCb++GAub0Bdb1hOwDWjDszJVNB0Fwnbmwbg1c="; + static implementationId = "sha256-WDzCMZOCx3LjXtedbEAvHx9txxgH1XLwetNqKakke+s="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1SegmentedControl }; diff --git a/packages/ui/dist/copy/segmented-control/runtime/register/segmented-control.js b/packages/ui/dist/copy/segmented-control/runtime/register/segmented-control.js index 526fd7f71..5786a67c5 100644 --- a/packages/ui/dist/copy/segmented-control/runtime/register/segmented-control.js +++ b/packages/ui/dist/copy/segmented-control/runtime/register/segmented-control.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1SegmentedControl } from "../components/segmented-control.js"; -//#region .cache/ui-build/entries/register/segmented-control.js +// .cache/ui-build/entries/register/segmented-control.js var element = registerElement("j3w1-segmented-control", J3w1SegmentedControl); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/select/manifest.json b/packages/ui/dist/copy/select/manifest.json index 8a5cbef07..4113938ba 100644 --- a/packages/ui/dist/copy/select/manifest.json +++ b/packages/ui/dist/copy/select/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/select.md", "dependencies": [ "register/select.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/select.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/select.js": "sha256-TN7apnaEDR69Eobpnesx4c3Yr2iU33xNGj/q9i+nFtw=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/select.js": "sha256-QSO5F4fiwtnnIHZ9/a9n62yVZRlGUIofNkw2oXYIzGY=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/select.js": "sha256-a/ebYoMxXf0lulroJxRYiTUDtJLmr23xOp4f3nhwepc=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/select.js": "sha256-5I3s1W7GlcelP7ffSDNZXafcFZmzILO7gFZrwhZh9Ps=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-F6DQsNcbPkf+LkJ534A3xYbg7WBsLszKxMa9zap0wK0=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/select/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/select/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/select/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/select/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/select/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/select/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/select/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/select/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/select/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/select/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/select/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/select/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/select/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/select/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/select/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/select/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/select/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/select/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/select/runtime/components/select.js b/packages/ui/dist/copy/select/runtime/components/select.js index a59b0acab..5adb3c6f7 100644 --- a/packages/ui/dist/copy/select/runtime/components/select.js +++ b/packages/ui/dist/copy/select/runtime/components/select.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/select.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/select.js var J3w1Select = class extends J3w1Element { static componentId = "select"; static version = "4.0.0"; - static implementationId = "sha256-/4CAqDSF84DTC0pEcQUtcmmtAaVge6ifWVX3elTZzLM="; + static implementationId = "sha256-ghLIdVGffsPUo96JXVnI3p2L5ORJKK/Xdu7X3DOz4m0="; static connect = fields; static upgradeProperties = [ "disabled", @@ -39,5 +39,4 @@ var J3w1Select = class extends J3w1Element { }); } }; -//#endregion export { J3w1Select }; diff --git a/packages/ui/dist/copy/select/runtime/register/select.js b/packages/ui/dist/copy/select/runtime/register/select.js index 6fcd3d855..64f3c5936 100644 --- a/packages/ui/dist/copy/select/runtime/register/select.js +++ b/packages/ui/dist/copy/select/runtime/register/select.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Select } from "../components/select.js"; -//#region .cache/ui-build/entries/register/select.js +// .cache/ui-build/entries/register/select.js var element = registerElement("j3w1-select", J3w1Select); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/settings-panel/manifest.json b/packages/ui/dist/copy/settings-panel/manifest.json index b80b35225..caea483b5 100644 --- a/packages/ui/dist/copy/settings-panel/manifest.json +++ b/packages/ui/dist/copy/settings-panel/manifest.json @@ -5,23 +5,23 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/settings-panel.md", "dependencies": [ "register/settings-panel.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "register/switch.js", "components/switch.js", - "chunks/native-BjBt1sUh.js", + "chunks/native-D61761VL.js", "components/settings-panel.js", - "chunks/forms-CE_hP1hg.js" + "chunks/forms-C3u5121t.js" ], "files": { - "runtime/register/settings-panel.js": "sha256-Ob0kL9R4vmbYJ7EqPNT3788vg2FpTs87xAsE1TbqHeg=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/register/switch.js": "sha256-6l7gxY7bHWXI4K8WMdikGfg6Itnf2Uy8hSbsvn+XCYM=", - "runtime/components/switch.js": "sha256-sdfSvJlKylAeDbhRKPMRUZ+piEOzKs1aV52BDvjOV/o=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", - "runtime/components/settings-panel.js": "sha256-2/vcKktPpt7/9RBfexqEoFAPjNDcISoi6AALg6/CVTw=", - "runtime/chunks/forms-CE_hP1hg.js": "sha256-uOnoMuSkUbm9C/GfR+PDLYCykyHOQ1Ni7g59c4YMOS0=", + "runtime/register/settings-panel.js": "sha256-9rj2m46hgJMosP85Z0xhOpSLAAL4iBWxUQVTwTmueq8=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/register/switch.js": "sha256-DuUxpd3L4nKgHvyJPWJ+2TZBOWxcTy0MOtxrbgEWF/I=", + "runtime/components/switch.js": "sha256-CVbrKOXLXh5ZRJ7UrRkrE+VgZ8zGcaD6GE1mYPPDdio=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", + "runtime/components/settings-panel.js": "sha256-XmcGNm6lxEdrb/RfdzNnk9NhOsMTTxK3Dv437FczSgY=", + "runtime/chunks/forms-C3u5121t.js": "sha256-DymhKeiaCcQj+DmkDxoEwP0Md4YxiSpCxyYS4eiMnV0=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-k+UkB8smqd63SQIr7NXfAoXvhCZooblbGmEzkIW0mz0=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/settings-panel/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/settings-panel/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/settings-panel/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/settings-panel/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/settings-panel/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/settings-panel/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/settings-panel/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/settings-panel/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/settings-panel/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/settings-panel/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/settings-panel/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/settings-panel/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/admin-form/runtime/chunks/forms-CE_hP1hg.js b/packages/ui/dist/copy/settings-panel/runtime/chunks/forms-C3u5121t.js similarity index 96% rename from packages/ui/dist/copy/admin-form/runtime/chunks/forms-CE_hP1hg.js rename to packages/ui/dist/copy/settings-panel/runtime/chunks/forms-C3u5121t.js index 6ad3b48f5..7eaab7c98 100644 --- a/packages/ui/dist/copy/admin-form/runtime/chunks/forms-CE_hP1hg.js +++ b/packages/ui/dist/copy/settings-panel/runtime/chunks/forms-C3u5121t.js @@ -1,5 +1,5 @@ -import { i as all, l as make, o as enabled } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/forms.js +import { i as all, l as make, o as enabled } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/forms.js function wizard(root, { on }) { const panels = all(root, ".wizard-panel"), steps = all(root, ".wizard-step-button"), backButton = root.querySelector(".wizard-back"), nextButton = root.querySelector(".wizard-next"); if (!panels.length || panels.length !== steps.length) throw new Error("A wizard requires one complete panel for each step button"); @@ -119,5 +119,4 @@ function formComposition(root, { on }) { if (root.querySelector("[data-start=\"review\"]")) showReview(false); return {}; } -//#endregion export { wizard as n, formComposition as t }; diff --git a/packages/ui/dist/copy/settings-panel/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/settings-panel/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/settings-panel/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/settings-panel/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/settings-panel/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/settings-panel/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/settings-panel/runtime/components/settings-panel.js b/packages/ui/dist/copy/settings-panel/runtime/components/settings-panel.js index 4d48521a3..d300eccec 100644 --- a/packages/ui/dist/copy/settings-panel/runtime/components/settings-panel.js +++ b/packages/ui/dist/copy/settings-panel/runtime/components/settings-panel.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as formComposition } from "../chunks/forms-CE_hP1hg.js"; -//#region .cache/ui-build/entries/components/settings-panel.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as formComposition } from "../chunks/forms-C3u5121t.js"; +// .cache/ui-build/entries/components/settings-panel.js var J3w1SettingsPanel = class extends J3w1Element { static componentId = "settings-panel"; static version = "4.0.0"; - static implementationId = "sha256-Or1edewP4Rk9HC/kFygK+IUyEoPDHJFEyWO9Acv3Ge4="; + static implementationId = "sha256-ED51an0ymCtlHkUQM0Sk0VgNjG1GK+ucBgtJAFTi2nI="; static connect = formComposition; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1SettingsPanel }; diff --git a/packages/ui/dist/copy/settings-panel/runtime/components/switch.js b/packages/ui/dist/copy/settings-panel/runtime/components/switch.js index 87c027482..5ca2e4f1d 100644 --- a/packages/ui/dist/copy/settings-panel/runtime/components/switch.js +++ b/packages/ui/dist/copy/settings-panel/runtime/components/switch.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { a as switchControl } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/switch.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { a as switchControl } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/switch.js var J3w1Switch = class extends J3w1Element { static componentId = "switch"; static version = "4.0.0"; - static implementationId = "sha256-FqTv7TNhvOBWq10QKBC1FBB+4Wxd4wo2qtt4bCUEvbA="; + static implementationId = "sha256-uj6lpt+JpOZ3eT8oXJm21YGJarcQjDoXnm/GwDmQmcI="; static connect = switchControl; static upgradeProperties = [ "disabled", @@ -29,5 +29,4 @@ var J3w1Switch = class extends J3w1Element { }); } }; -//#endregion export { J3w1Switch }; diff --git a/packages/ui/dist/copy/settings-panel/runtime/register/settings-panel.js b/packages/ui/dist/copy/settings-panel/runtime/register/settings-panel.js index 0067d590e..ff58d2008 100644 --- a/packages/ui/dist/copy/settings-panel/runtime/register/settings-panel.js +++ b/packages/ui/dist/copy/settings-panel/runtime/register/settings-panel.js @@ -1,7 +1,6 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import "./switch.js"; import { J3w1SettingsPanel } from "../components/settings-panel.js"; -//#region .cache/ui-build/entries/register/settings-panel.js +// .cache/ui-build/entries/register/settings-panel.js var element = registerElement("j3w1-settings-panel", J3w1SettingsPanel); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/settings-panel/runtime/register/switch.js b/packages/ui/dist/copy/settings-panel/runtime/register/switch.js index 5e227ec0d..c6ab85198 100644 --- a/packages/ui/dist/copy/settings-panel/runtime/register/switch.js +++ b/packages/ui/dist/copy/settings-panel/runtime/register/switch.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Switch } from "../components/switch.js"; -//#region .cache/ui-build/entries/register/switch.js +// .cache/ui-build/entries/register/switch.js var element = registerElement("j3w1-switch", J3w1Switch); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/sidebar-nav/manifest.json b/packages/ui/dist/copy/sidebar-nav/manifest.json index 458e671ec..ea38f93de 100644 --- a/packages/ui/dist/copy/sidebar-nav/manifest.json +++ b/packages/ui/dist/copy/sidebar-nav/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/sidebar-nav.md", "dependencies": [ "register/sidebar-nav.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/sidebar-nav.js", - "chunks/navigation-BfNzDYZB.js" + "chunks/navigation-CknoksQ5.js" ], "files": { - "runtime/register/sidebar-nav.js": "sha256-wezN/wQaG+kQGmgqJIj3iSl5mFjjKr0DJLl9jLsnRFA=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/sidebar-nav.js": "sha256-DZRlRYGAhBJm3yZ1nqAoW67+PcYUqE3uCTEEnKa9NFQ=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", + "runtime/register/sidebar-nav.js": "sha256-4Bq41zeEEBKMEmVQYRFSAsKz16A6HbWtI61B0pyIR1w=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/sidebar-nav.js": "sha256-/IIf4o9f34122fyLRdFcxXOsCbG1deNnKEExODzSGJ0=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-LJ8LLDvQsYO50EORdep12yfyTFwnO4BxbDzOwHYpciA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/sidebar-nav/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/sidebar-nav/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/sidebar-nav/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/sidebar-nav/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/sidebar-nav/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/sidebar-nav/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/sidebar-nav/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/sidebar-nav/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/sidebar-nav/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/sidebar-nav/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/sidebar-nav/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/sidebar-nav/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/sidebar-nav/runtime/chunks/navigation-BfNzDYZB.js b/packages/ui/dist/copy/sidebar-nav/runtime/chunks/navigation-BfNzDYZB.js deleted file mode 100644 index db2779553..000000000 --- a/packages/ui/dist/copy/sidebar-nav/runtime/chunks/navigation-BfNzDYZB.js +++ /dev/null @@ -1,377 +0,0 @@ -import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/navigation.js -function tabs(root, { on }, listOverride) { - const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); - if (!list) return {}; - const items = () => all(list, "[role=\"tab\"]").filter(enabled); - const select = (id, focus = false) => { - const tab = items().find((item) => item.id === id); - if (!tab) throw new RangeError(`Unknown enabled tab: ${id}`); - all(list, "[role=\"tab\"]").forEach((item) => { - item.setAttribute("aria-selected", String(item === tab)); - item.tabIndex = item === tab ? 0 : -1; - }); - all(root, "[role=\"tabpanel\"]").filter((panel) => all(list, "[role=\"tab\"]").some((tab) => tab.getAttribute("aria-controls") === panel.id)).forEach((panel) => { - panel.hidden = panel.id !== tab.getAttribute("aria-controls"); - if (!panel.hidden && !panel.querySelector("a[href],button,input,select,textarea,[tabindex='0']")) panel.tabIndex = 0; - }); - if (focus) tab.focus(); - return tab; - }; - const activate = (tab) => { - select(tab.id); - root.emit("select", { - id: tab.id, - panelId: tab.getAttribute("aria-controls") - }); - }; - on(list, "click", (event) => { - const tab = event.target.closest("[role=\"tab\"]"); - if (tab && enabled(tab)) activate(tab); - }); - on(list, "keydown", (event) => { - const current = event.target.closest("[role=\"tab\"]"), options = items(); - if (!current) return; - const vertical = list.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(list).direction === "rtl"; - const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", previous = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; - let index = options.indexOf(current); - if (event.key === next) index++; - else if (event.key === previous) index--; - else if (event.key === "Home") index = 0; - else if (event.key === "End") index = options.length - 1; - else if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - activate(current); - return; - } else return; - event.preventDefault(); - const tab = rove(options, index); - if (root.getAttribute("activation") !== "manual") activate(tab); - }); - const initial = items().find((item) => item.getAttribute("aria-selected") === "true") ?? items()[0]; - if (initial) select(initial.id); - return { - select, - get selectedId() { - return list.querySelector("[aria-selected=\"true\"]")?.id ?? ""; - }, - set selectedId(id) { - select(id); - } - }; -} -function toolbar(root, { on }) { - const bar = root.querySelector("[role=\"toolbar\"]"); - if (!bar) return {}; - const controls = () => all(bar, "button,a[href],input,select").filter((node) => enabled(node) && visible(node) && !node.closest("[role=\"menu\"]")); - const initial = controls(); - rove(initial, Math.max(0, initial.findIndex((node) => node.tabIndex === 0)), false); - on(bar, "focusin", (event) => { - if (controls().includes(event.target)) rove(controls(), controls().indexOf(event.target), false); - }); - on(bar, "keydown", (event) => { - if (event.target.matches("input,select,textarea") || event.target.closest("[role=\"menu\"]")) return; - const items = controls(), index = items.indexOf(event.target); - const vertical = bar.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(bar).direction === "rtl"; - const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", prev = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; - if (![ - next, - prev, - "Home", - "End" - ].includes(event.key)) return; - event.preventDefault(); - rove(items, keyIndex({ - key: event.key, - index, - length: items.length, - next, - previous: prev - })); - }); - on(bar, "click", (event) => { - const button = event.target.closest("button[aria-pressed]"); - if (button && enabled(button)) { - button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - root.emit("action", { - action: button.dataset.action ?? button.textContent.trim(), - pressed: button.getAttribute("aria-pressed") === "true" - }); - } - }); - return {}; -} -function disclosure(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button[aria-controls][aria-expanded]"); - if (!button || !enabled(button)) return; - const target = root.querySelector(`#${CSS.escape(button.getAttribute("aria-controls"))}`); - if (!target) return; - const expanded = button.getAttribute("aria-expanded") !== "true"; - button.setAttribute("aria-expanded", String(expanded)); - target.hidden = !expanded; - root.emit("toggle", { - id: target.id, - expanded - }); - }); - const details = root.querySelector("details"); - on(details, "toggle", () => root.emit("toggle", { - id: details.id, - expanded: details.open - })); - return { - get open() { - return details?.open ?? false; - }, - set open(value) { - if (details) details.open = Boolean(value); - } - }; -} -function combobox(root, { on, signal }) { - const input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"); - if (!input || !list) return {}; - identify(root, list, "options"); - input.setAttribute("aria-controls", list.id); - let active = null, notifying = false; - const notify = () => { - notifying = true; - try { - nativeInput(input); - nativeInput(input, "change"); - } finally { - notifying = false; - } - }; - const options = () => all(list, "[role=\"option\"]").filter((node) => enabled(node) && !node.hidden && !node.closest("[role=\"group\"][hidden]")); - all(list, "[role=\"option\"]").forEach((option, index) => identify(root, option, `option-${index}`)); - const setActive = (option) => { - active = option; - all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); - if (option) { - input.setAttribute("aria-activedescendant", option.id); - option.scrollIntoView({ block: "nearest" }); - } else input.removeAttribute("aria-activedescendant"); - }; - const hide = () => { - list.hidden = true; - input.setAttribute("aria-expanded", "false"); - setActive(null); - }; - const filter = (query = input.value) => { - for (const option of all(list, "[role=\"option\"]")) if (enabled(option)) option.hidden = !option.textContent.toLocaleLowerCase().includes(query.toLocaleLowerCase()); - all(list, "[role=\"group\"]").forEach((group) => { - group.hidden = !all(group, "[role=\"option\"]").some((node) => enabled(node) && !node.hidden); - }); - const empty = root.querySelector(".combobox-empty"); - if (empty) { - empty.hidden = options().length !== 0; - empty.classList.toggle("combobox-empty-shown", !empty.hidden); - } - if (!options().includes(active)) setActive(null); - }; - const show = (allOptions = false) => { - if (!enabled(input) || input.readOnly) return; - filter(allOptions ? "" : input.value); - list.hidden = false; - input.setAttribute("aria-expanded", "true"); - place(input, list); - }; - const choose = (option) => { - if (!option || !enabled(option)) return; - input.value = option.dataset.value ?? option.textContent.trim(); - hide(); - notify(); - input.focus(); - }; - on(input, "input", () => { - if (!notifying) { - show(); - announce(root, `${options().length} options available.`); - } - }); - on(input, "keydown", (event) => { - if (event.key === "Tab") { - hide(); - return; - } - if (event.key === "Escape") { - if (!list.hidden) { - hide(); - event.stopPropagation(); - } else if (input.value) { - input.value = ""; - notify(); - event.stopPropagation(); - } - event.preventDefault(); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - hide(); - return; - } - if (["ArrowDown", "ArrowUp"].includes(event.key)) { - event.preventDefault(); - if (list.hidden) show(true); - if (event.altKey) return; - const items = options(), index = active ? items.indexOf(active) : event.key === "ArrowDown" ? -1 : 0; - if (items.length) setActive(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); - } else if (event.key === "Enter" && !list.hidden && active) { - event.preventDefault(); - choose(active); - } - }); - on(list, "pointerdown", (event) => { - if (event.target.closest("[role=\"option\"]")) event.preventDefault(); - }); - on(list, "click", (event) => choose(event.target.closest("[role=\"option\"]"))); - on(root.querySelector(".combobox-toggle"), "click", () => { - list.hidden ? show(true) : hide(); - input.focus(); - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!root.contains(event.target)) hide(); - }); - on(root, "focusout", () => queueMicrotask(() => { - if (!signal.aborted && !root.contains(root.ownerDocument.activeElement)) hide(); - })); - on(root.ownerDocument.defaultView, "resize", () => { - if (!list.hidden) place(input, list); - }); - on(root.ownerDocument, "scroll", (event) => { - if (!list.hidden && !list.contains(event.target)) place(input, list); - }, { capture: true }); - hide(); - return { - show, - hide, - get open() { - return !list.hidden; - }, - set open(value) { - value ? show() : hide(); - }, - get value() { - return input.value; - }, - set value(value) { - input.value = String(value ?? ""); - if (!list.hidden) filter(); - }, - cleanup: hide - }; -} -function menu(root, { on }) { - const trigger = root.querySelector("button[aria-haspopup=\"menu\"]"), main = root.querySelector("[role=\"menu\"]"); - if (!trigger || !main) return {}; - identify(root, main, "menu"); - trigger.setAttribute("aria-controls", main.id); - const lists = all(root, "[role=\"menu\"]"); - const items = (list) => all(list, "[role^=\"menuitem\"]").filter((item) => item.closest("[role=\"menu\"]") === list); - const controller = (list) => all(root, "[aria-controls]").find((node) => node.getAttribute("aria-controls") === list.id); - const closeList = (list) => { - list.hidden = true; - controller(list)?.setAttribute("aria-expanded", "false"); - }; - const hide = (focus = true) => { - lists.forEach(closeList); - if (focus) trigger.focus(); - }; - const showList = (list, button, last = false) => { - list.hidden = false; - button.setAttribute("aria-expanded", "true"); - place(button, list); - rove(items(list), last ? items(list).length - 1 : 0); - }; - const show = () => { - if (enabled(trigger)) showList(main, trigger); - }; - const submenu = (button) => button.hasAttribute("aria-haspopup") ? lists.find((list) => list.id === button.getAttribute("aria-controls")) : null; - const activate = (item) => { - if (!enabled(item)) return; - const child = submenu(item); - if (child) { - showList(child, item); - return; - } - if (item.getAttribute("role") === "menuitemcheckbox") item.setAttribute("aria-checked", String(item.getAttribute("aria-checked") !== "true")); - else if (item.getAttribute("role") === "menuitemradio") items(item.closest("[role=\"menu\"]")).filter((node) => node.getAttribute("role") === "menuitemradio").forEach((node) => node.setAttribute("aria-checked", String(node === item))); - else hide(); - root.emit("action", { - action: item.dataset.action ?? item.textContent.trim(), - checked: item.getAttribute("aria-checked") === "true" - }); - }; - on(trigger, "click", () => main.hidden ? show() : hide()); - on(trigger, "keydown", (event) => { - if (["ArrowDown", "ArrowUp"].includes(event.key) && enabled(trigger)) { - event.preventDefault(); - showList(main, trigger, event.key === "ArrowUp"); - } - }); - on(root, "click", (event) => { - const item = event.target.closest("[role^=\"menuitem\"]"); - if (item) activate(item); - }); - on(root, "keydown", (event) => { - const item = event.target.closest("[role^=\"menuitem\"]"); - if (!item) return; - const list = item.closest("[role=\"menu\"]"), options = items(list), index = options.indexOf(item), rtl = getComputedStyle(list).direction === "rtl"; - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - rove(options, keyIndex({ - key: event.key, - index, - length: options.length - })); - } else if (event.key === "Escape" || event.key === (rtl ? "ArrowRight" : "ArrowLeft") && list !== main) { - event.preventDefault(); - event.stopPropagation(); - if (list !== main) { - closeList(list); - controller(list)?.focus(); - } else hide(); - } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight") && submenu(item)) { - event.preventDefault(); - showList(submenu(item), item); - } else if (event.key === "Tab") hide(); - else if (event.key.length === 1 && /\S/.test(event.key)) { - const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(".menu-label") ?? node).textContent.trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); - if (found) { - event.preventDefault(); - rove(options, options.indexOf(found)); - } - } - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!root.contains(event.target)) hide(false); - }); - on(root.ownerDocument, "focusin", (event) => { - if (!root.contains(event.target)) hide(false); - }); - on(root.ownerDocument.defaultView, "resize", () => lists.filter((list) => !list.hidden).forEach((list) => place(controller(list), list))); - hide(false); - return { - show, - hide, - get open() { - return !main.hidden; - }, - set open(value) { - value ? show() : hide(false); - }, - cleanup() { - hide(false); - } - }; -} -//#endregion -export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/sidebar-nav/runtime/chunks/navigation-CknoksQ5.js b/packages/ui/dist/copy/sidebar-nav/runtime/chunks/navigation-CknoksQ5.js new file mode 100644 index 000000000..dfd1883e6 --- /dev/null +++ b/packages/ui/dist/copy/sidebar-nav/runtime/chunks/navigation-CknoksQ5.js @@ -0,0 +1,376 @@ +import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/navigation.js +function tabs(root, { on }, listOverride) { + const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); + if (!list) return {}; + const items = () => all(list, "[role=\"tab\"]").filter(enabled); + const select = (id, focus = false) => { + const tab = items().find((item) => item.id === id); + if (!tab) throw new RangeError(`Unknown enabled tab: ${id}`); + all(list, "[role=\"tab\"]").forEach((item) => { + item.setAttribute("aria-selected", String(item === tab)); + item.tabIndex = item === tab ? 0 : -1; + }); + all(root, "[role=\"tabpanel\"]").filter((panel) => all(list, "[role=\"tab\"]").some((tab) => tab.getAttribute("aria-controls") === panel.id)).forEach((panel) => { + panel.hidden = panel.id !== tab.getAttribute("aria-controls"); + if (!panel.hidden && !panel.querySelector("a[href],button,input,select,textarea,[tabindex='0']")) panel.tabIndex = 0; + }); + if (focus) tab.focus(); + return tab; + }; + const activate = (tab) => { + select(tab.id); + root.emit("select", { + id: tab.id, + panelId: tab.getAttribute("aria-controls") + }); + }; + on(list, "click", (event) => { + const tab = event.target.closest("[role=\"tab\"]"); + if (tab && enabled(tab)) activate(tab); + }); + on(list, "keydown", (event) => { + const current = event.target.closest("[role=\"tab\"]"), options = items(); + if (!current) return; + const vertical = list.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(list).direction === "rtl"; + const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", previous = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; + let index = options.indexOf(current); + if (event.key === next) index++; + else if (event.key === previous) index--; + else if (event.key === "Home") index = 0; + else if (event.key === "End") index = options.length - 1; + else if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + activate(current); + return; + } else return; + event.preventDefault(); + const tab = rove(options, index); + if (root.getAttribute("activation") !== "manual") activate(tab); + }); + const initial = items().find((item) => item.getAttribute("aria-selected") === "true") ?? items()[0]; + if (initial) select(initial.id); + return { + select, + get selectedId() { + return list.querySelector("[aria-selected=\"true\"]")?.id ?? ""; + }, + set selectedId(id) { + select(id); + } + }; +} +function toolbar(root, { on }) { + const bar = root.querySelector("[role=\"toolbar\"]"); + if (!bar) return {}; + const controls = () => all(bar, "button,a[href],input,select").filter((node) => enabled(node) && visible(node) && !node.closest("[role=\"menu\"]")); + const initial = controls(); + rove(initial, Math.max(0, initial.findIndex((node) => node.tabIndex === 0)), false); + on(bar, "focusin", (event) => { + if (controls().includes(event.target)) rove(controls(), controls().indexOf(event.target), false); + }); + on(bar, "keydown", (event) => { + if (event.target.matches("input,select,textarea") || event.target.closest("[role=\"menu\"]")) return; + const items = controls(), index = items.indexOf(event.target); + const vertical = bar.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(bar).direction === "rtl"; + const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", prev = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; + if (![ + next, + prev, + "Home", + "End" + ].includes(event.key)) return; + event.preventDefault(); + rove(items, keyIndex({ + key: event.key, + index, + length: items.length, + next, + previous: prev + })); + }); + on(bar, "click", (event) => { + const button = event.target.closest("button[aria-pressed]"); + if (button && enabled(button)) { + button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + root.emit("action", { + action: button.dataset.action ?? button.textContent.trim(), + pressed: button.getAttribute("aria-pressed") === "true" + }); + } + }); + return {}; +} +function disclosure(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button[aria-controls][aria-expanded]"); + if (!button || !enabled(button)) return; + const target = root.querySelector(`#${CSS.escape(button.getAttribute("aria-controls"))}`); + if (!target) return; + const expanded = button.getAttribute("aria-expanded") !== "true"; + button.setAttribute("aria-expanded", String(expanded)); + target.hidden = !expanded; + root.emit("toggle", { + id: target.id, + expanded + }); + }); + const details = root.querySelector("details"); + on(details, "toggle", () => root.emit("toggle", { + id: details.id, + expanded: details.open + })); + return { + get open() { + return details?.open ?? false; + }, + set open(value) { + if (details) details.open = Boolean(value); + } + }; +} +function combobox(root, { on, signal }) { + const input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"); + if (!input || !list) return {}; + identify(root, list, "options"); + input.setAttribute("aria-controls", list.id); + let active = null, notifying = false; + const notify = () => { + notifying = true; + try { + nativeInput(input); + nativeInput(input, "change"); + } finally { + notifying = false; + } + }; + const options = () => all(list, "[role=\"option\"]").filter((node) => enabled(node) && !node.hidden && !node.closest("[role=\"group\"][hidden]")); + all(list, "[role=\"option\"]").forEach((option, index) => identify(root, option, `option-${index}`)); + const setActive = (option) => { + active = option; + all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); + if (option) { + input.setAttribute("aria-activedescendant", option.id); + option.scrollIntoView({ block: "nearest" }); + } else input.removeAttribute("aria-activedescendant"); + }; + const hide = () => { + list.hidden = true; + input.setAttribute("aria-expanded", "false"); + setActive(null); + }; + const filter = (query = input.value) => { + for (const option of all(list, "[role=\"option\"]")) if (enabled(option)) option.hidden = !option.textContent.toLocaleLowerCase().includes(query.toLocaleLowerCase()); + all(list, "[role=\"group\"]").forEach((group) => { + group.hidden = !all(group, "[role=\"option\"]").some((node) => enabled(node) && !node.hidden); + }); + const empty = root.querySelector(".combobox-empty"); + if (empty) { + empty.hidden = options().length !== 0; + empty.classList.toggle("combobox-empty-shown", !empty.hidden); + } + if (!options().includes(active)) setActive(null); + }; + const show = (allOptions = false) => { + if (!enabled(input) || input.readOnly) return; + filter(allOptions ? "" : input.value); + list.hidden = false; + input.setAttribute("aria-expanded", "true"); + place(input, list); + }; + const choose = (option) => { + if (!option || !enabled(option)) return; + input.value = option.dataset.value ?? option.textContent.trim(); + hide(); + notify(); + input.focus(); + }; + on(input, "input", () => { + if (!notifying) { + show(); + announce(root, `${options().length} options available.`); + } + }); + on(input, "keydown", (event) => { + if (event.key === "Tab") { + hide(); + return; + } + if (event.key === "Escape") { + if (!list.hidden) { + hide(); + event.stopPropagation(); + } else if (input.value) { + input.value = ""; + notify(); + event.stopPropagation(); + } + event.preventDefault(); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + hide(); + return; + } + if (["ArrowDown", "ArrowUp"].includes(event.key)) { + event.preventDefault(); + if (list.hidden) show(true); + if (event.altKey) return; + const items = options(), index = active ? items.indexOf(active) : event.key === "ArrowDown" ? -1 : 0; + if (items.length) setActive(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); + } else if (event.key === "Enter" && !list.hidden && active) { + event.preventDefault(); + choose(active); + } + }); + on(list, "pointerdown", (event) => { + if (event.target.closest("[role=\"option\"]")) event.preventDefault(); + }); + on(list, "click", (event) => choose(event.target.closest("[role=\"option\"]"))); + on(root.querySelector(".combobox-toggle"), "click", () => { + list.hidden ? show(true) : hide(); + input.focus(); + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!root.contains(event.target)) hide(); + }); + on(root, "focusout", () => queueMicrotask(() => { + if (!signal.aborted && !root.contains(root.ownerDocument.activeElement)) hide(); + })); + on(root.ownerDocument.defaultView, "resize", () => { + if (!list.hidden) place(input, list); + }); + on(root.ownerDocument, "scroll", (event) => { + if (!list.hidden && !list.contains(event.target)) place(input, list); + }, { capture: true }); + hide(); + return { + show, + hide, + get open() { + return !list.hidden; + }, + set open(value) { + value ? show() : hide(); + }, + get value() { + return input.value; + }, + set value(value) { + input.value = String(value ?? ""); + if (!list.hidden) filter(); + }, + cleanup: hide + }; +} +function menu(root, { on }) { + const trigger = root.querySelector("button[aria-haspopup=\"menu\"]"), main = root.querySelector("[role=\"menu\"]"); + if (!trigger || !main) return {}; + identify(root, main, "menu"); + trigger.setAttribute("aria-controls", main.id); + const lists = all(root, "[role=\"menu\"]"); + const items = (list) => all(list, "[role^=\"menuitem\"]").filter((item) => item.closest("[role=\"menu\"]") === list); + const controller = (list) => all(root, "[aria-controls]").find((node) => node.getAttribute("aria-controls") === list.id); + const closeList = (list) => { + list.hidden = true; + controller(list)?.setAttribute("aria-expanded", "false"); + }; + const hide = (focus = true) => { + lists.forEach(closeList); + if (focus) trigger.focus(); + }; + const showList = (list, button, last = false) => { + list.hidden = false; + button.setAttribute("aria-expanded", "true"); + place(button, list); + rove(items(list), last ? items(list).length - 1 : 0); + }; + const show = () => { + if (enabled(trigger)) showList(main, trigger); + }; + const submenu = (button) => button.hasAttribute("aria-haspopup") ? lists.find((list) => list.id === button.getAttribute("aria-controls")) : null; + const activate = (item) => { + if (!enabled(item)) return; + const child = submenu(item); + if (child) { + showList(child, item); + return; + } + if (item.getAttribute("role") === "menuitemcheckbox") item.setAttribute("aria-checked", String(item.getAttribute("aria-checked") !== "true")); + else if (item.getAttribute("role") === "menuitemradio") items(item.closest("[role=\"menu\"]")).filter((node) => node.getAttribute("role") === "menuitemradio").forEach((node) => node.setAttribute("aria-checked", String(node === item))); + else hide(); + root.emit("action", { + action: item.dataset.action ?? item.textContent.trim(), + checked: item.getAttribute("aria-checked") === "true" + }); + }; + on(trigger, "click", () => main.hidden ? show() : hide()); + on(trigger, "keydown", (event) => { + if (["ArrowDown", "ArrowUp"].includes(event.key) && enabled(trigger)) { + event.preventDefault(); + showList(main, trigger, event.key === "ArrowUp"); + } + }); + on(root, "click", (event) => { + const item = event.target.closest("[role^=\"menuitem\"]"); + if (item) activate(item); + }); + on(root, "keydown", (event) => { + const item = event.target.closest("[role^=\"menuitem\"]"); + if (!item) return; + const list = item.closest("[role=\"menu\"]"), options = items(list), index = options.indexOf(item), rtl = getComputedStyle(list).direction === "rtl"; + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + rove(options, keyIndex({ + key: event.key, + index, + length: options.length + })); + } else if (event.key === "Escape" || event.key === (rtl ? "ArrowRight" : "ArrowLeft") && list !== main) { + event.preventDefault(); + event.stopPropagation(); + if (list !== main) { + closeList(list); + controller(list)?.focus(); + } else hide(); + } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight") && submenu(item)) { + event.preventDefault(); + showList(submenu(item), item); + } else if (event.key === "Tab") hide(); + else if (event.key.length === 1 && /\S/.test(event.key)) { + const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(".menu-label") ?? node).textContent.trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); + if (found) { + event.preventDefault(); + rove(options, options.indexOf(found)); + } + } + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!root.contains(event.target)) hide(false); + }); + on(root.ownerDocument, "focusin", (event) => { + if (!root.contains(event.target)) hide(false); + }); + on(root.ownerDocument.defaultView, "resize", () => lists.filter((list) => !list.hidden).forEach((list) => place(controller(list), list))); + hide(false); + return { + show, + hide, + get open() { + return !main.hidden; + }, + set open(value) { + value ? show() : hide(false); + }, + cleanup() { + hide(false); + } + }; +} +export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/sidebar-nav/runtime/components/sidebar-nav.js b/packages/ui/dist/copy/sidebar-nav/runtime/components/sidebar-nav.js index 03f391cbd..d1c922672 100644 --- a/packages/ui/dist/copy/sidebar-nav/runtime/components/sidebar-nav.js +++ b/packages/ui/dist/copy/sidebar-nav/runtime/components/sidebar-nav.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as disclosure } from "../chunks/navigation-BfNzDYZB.js"; -//#region .cache/ui-build/entries/components/sidebar-nav.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as disclosure } from "../chunks/navigation-CknoksQ5.js"; +// .cache/ui-build/entries/components/sidebar-nav.js var J3w1SidebarNav = class extends J3w1Element { static componentId = "sidebar-nav"; static version = "4.0.0"; - static implementationId = "sha256-rKjBWaKv0/VZBCTIvYNnUx/X/HyPypn7MJrL9+nt6cM="; + static implementationId = "sha256-p1RculkZB6rOKcsc85xvS+ftYOHY9F7U48/gV/8p3dk="; static connect = disclosure; static upgradeProperties = [ "disabled", @@ -24,5 +24,4 @@ var J3w1SidebarNav = class extends J3w1Element { }); } }; -//#endregion export { J3w1SidebarNav }; diff --git a/packages/ui/dist/copy/sidebar-nav/runtime/register/sidebar-nav.js b/packages/ui/dist/copy/sidebar-nav/runtime/register/sidebar-nav.js index 59f4cc44a..3c1befc93 100644 --- a/packages/ui/dist/copy/sidebar-nav/runtime/register/sidebar-nav.js +++ b/packages/ui/dist/copy/sidebar-nav/runtime/register/sidebar-nav.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1SidebarNav } from "../components/sidebar-nav.js"; -//#region .cache/ui-build/entries/register/sidebar-nav.js +// .cache/ui-build/entries/register/sidebar-nav.js var element = registerElement("j3w1-sidebar-nav", J3w1SidebarNav); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/skeleton/manifest.json b/packages/ui/dist/copy/skeleton/manifest.json index 7ec0d9bb1..e65c3efb1 100644 --- a/packages/ui/dist/copy/skeleton/manifest.json +++ b/packages/ui/dist/copy/skeleton/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/skeleton.md", "dependencies": [ "register/skeleton.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/skeleton.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/skeleton.js": "sha256-JdObZ43D4BCk7fNL7BZvz8hcDULGiVrwvC7nVz4lwFE=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/skeleton.js": "sha256-WSpVLmYkqKadgGqtEfd4Hma86gL9cG2QQC4FW0BXHKw=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/skeleton.js": "sha256-hbvs0AFMUUdqWlgc7sQW92NsxfPob/qt8wzn3y6gYTw=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/skeleton.js": "sha256-7goo0hT+UPHFncfxVWpEL6gxQb2ZyUWp08MM9rJHWWU=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-Fdg05sQx+/Q5Ia/CN1d6mo9ueZkpbJnBwTnVSbNePgA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/skeleton/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/skeleton/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/skeleton/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/skeleton/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/skeleton/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/skeleton/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/skeleton/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/skeleton/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/skeleton/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/skeleton/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/skeleton/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/skeleton/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/skeleton/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/skeleton/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/skeleton/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/skeleton/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/skeleton/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/skeleton/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/skeleton/runtime/components/skeleton.js b/packages/ui/dist/copy/skeleton/runtime/components/skeleton.js index 16c0393a3..048e9f976 100644 --- a/packages/ui/dist/copy/skeleton/runtime/components/skeleton.js +++ b/packages/ui/dist/copy/skeleton/runtime/components/skeleton.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/skeleton.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/skeleton.js var J3w1Skeleton = class extends J3w1Element { static componentId = "skeleton"; static version = "4.0.0"; - static implementationId = "sha256-ZyHv2dS6YAfZGShU1uHi9YjORc4siAkmG4ledp4rX5I="; + static implementationId = "sha256-a+nQWoa3UR7bvtD3UARr6/n5WMa+YIA0/LDJorNqkN8="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Skeleton }; diff --git a/packages/ui/dist/copy/skeleton/runtime/register/skeleton.js b/packages/ui/dist/copy/skeleton/runtime/register/skeleton.js index ed0ab489a..e4ef771a6 100644 --- a/packages/ui/dist/copy/skeleton/runtime/register/skeleton.js +++ b/packages/ui/dist/copy/skeleton/runtime/register/skeleton.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Skeleton } from "../components/skeleton.js"; -//#region .cache/ui-build/entries/register/skeleton.js +// .cache/ui-build/entries/register/skeleton.js var element = registerElement("j3w1-skeleton", J3w1Skeleton); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/skip-link/manifest.json b/packages/ui/dist/copy/skip-link/manifest.json index 54584e694..70da40302 100644 --- a/packages/ui/dist/copy/skip-link/manifest.json +++ b/packages/ui/dist/copy/skip-link/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/skip-link.md", "dependencies": [ "register/skip-link.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/skip-link.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/skip-link.js": "sha256-GO29Wu/J6tcKAaNSyJEft5Nuiyn1QXF0x+VY1acaNuA=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/skip-link.js": "sha256-MomchP1kmj8/eRX8uVLTPeXPPhyYI18353abxwxtqTo=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/skip-link.js": "sha256-rdQErALjG6gRS2crzShW/TexAUbYpuBEGDW5L/xETEU=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/skip-link.js": "sha256-OzQweNJslHEVKrG1S2NnaBeW4GQAlBmb150UHci4dfI=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-AX9f8HRHYyMt1utmAsrIP+UncKsDILTwMv4qUMxNku0=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/skip-link/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/skip-link/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/skip-link/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/skip-link/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/skip-link/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/skip-link/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/skip-link/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/skip-link/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/skip-link/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/skip-link/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/skip-link/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/skip-link/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/skip-link/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/skip-link/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/skip-link/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/skip-link/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/skip-link/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/skip-link/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/skip-link/runtime/components/skip-link.js b/packages/ui/dist/copy/skip-link/runtime/components/skip-link.js index 65021bd9d..6731a0c7a 100644 --- a/packages/ui/dist/copy/skip-link/runtime/components/skip-link.js +++ b/packages/ui/dist/copy/skip-link/runtime/components/skip-link.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/skip-link.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/skip-link.js var J3w1SkipLink = class extends J3w1Element { static componentId = "skip-link"; static version = "4.0.0"; - static implementationId = "sha256-S77cz706XKgfI8OMLIyAhZab0PRCJkMplNQrcZjKP3c="; + static implementationId = "sha256-m2YbsLKFuE2LVJUIBlNoW28ON58/n56665mSGjucoHw="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1SkipLink }; diff --git a/packages/ui/dist/copy/skip-link/runtime/register/skip-link.js b/packages/ui/dist/copy/skip-link/runtime/register/skip-link.js index 7f93eeef8..e89b5a13a 100644 --- a/packages/ui/dist/copy/skip-link/runtime/register/skip-link.js +++ b/packages/ui/dist/copy/skip-link/runtime/register/skip-link.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1SkipLink } from "../components/skip-link.js"; -//#region .cache/ui-build/entries/register/skip-link.js +// .cache/ui-build/entries/register/skip-link.js var element = registerElement("j3w1-skip-link", J3w1SkipLink); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/switch/manifest.json b/packages/ui/dist/copy/switch/manifest.json index 9f53b7df3..598238c40 100644 --- a/packages/ui/dist/copy/switch/manifest.json +++ b/packages/ui/dist/copy/switch/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/switch.md", "dependencies": [ "register/switch.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/switch.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/switch.js": "sha256-6l7gxY7bHWXI4K8WMdikGfg6Itnf2Uy8hSbsvn+XCYM=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/switch.js": "sha256-sdfSvJlKylAeDbhRKPMRUZ+piEOzKs1aV52BDvjOV/o=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/switch.js": "sha256-DuUxpd3L4nKgHvyJPWJ+2TZBOWxcTy0MOtxrbgEWF/I=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/switch.js": "sha256-CVbrKOXLXh5ZRJ7UrRkrE+VgZ8zGcaD6GE1mYPPDdio=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-tykFKJCLb7EnJ9BYN4wbrmCaS+Vo3TtOvIKoQ1viFfI=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/switch/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/switch/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/switch/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/switch/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/switch/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/switch/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/switch/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/switch/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/switch/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/switch/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/switch/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/switch/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/switch/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/switch/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/switch/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/switch/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/switch/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/switch/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/switch/runtime/components/switch.js b/packages/ui/dist/copy/switch/runtime/components/switch.js index 87c027482..5ca2e4f1d 100644 --- a/packages/ui/dist/copy/switch/runtime/components/switch.js +++ b/packages/ui/dist/copy/switch/runtime/components/switch.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { a as switchControl } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/switch.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { a as switchControl } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/switch.js var J3w1Switch = class extends J3w1Element { static componentId = "switch"; static version = "4.0.0"; - static implementationId = "sha256-FqTv7TNhvOBWq10QKBC1FBB+4Wxd4wo2qtt4bCUEvbA="; + static implementationId = "sha256-uj6lpt+JpOZ3eT8oXJm21YGJarcQjDoXnm/GwDmQmcI="; static connect = switchControl; static upgradeProperties = [ "disabled", @@ -29,5 +29,4 @@ var J3w1Switch = class extends J3w1Element { }); } }; -//#endregion export { J3w1Switch }; diff --git a/packages/ui/dist/copy/switch/runtime/register/switch.js b/packages/ui/dist/copy/switch/runtime/register/switch.js index 5e227ec0d..c6ab85198 100644 --- a/packages/ui/dist/copy/switch/runtime/register/switch.js +++ b/packages/ui/dist/copy/switch/runtime/register/switch.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Switch } from "../components/switch.js"; -//#region .cache/ui-build/entries/register/switch.js +// .cache/ui-build/entries/register/switch.js var element = registerElement("j3w1-switch", J3w1Switch); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/table/manifest.json b/packages/ui/dist/copy/table/manifest.json index e220abf93..35c58386f 100644 --- a/packages/ui/dist/copy/table/manifest.json +++ b/packages/ui/dist/copy/table/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/table.md", "dependencies": [ "register/table.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/table.js", - "chunks/tables-Cjr1EIJz.js" + "chunks/tables-zo8ebTOo.js" ], "files": { - "runtime/register/table.js": "sha256-+Up9lgrfevvvIUF9vuOOwKxw0nDOAU/VctLLKZ73sd8=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/table.js": "sha256-CcoLzw/lwTUDE+3sCYBoQQoZAlE++zhK1ZLZELpyYN4=", - "runtime/chunks/tables-Cjr1EIJz.js": "sha256-K6BF6M6xNawgWdL+NIcBRZmY98j45o69tBI034Ks4Bg=", + "runtime/register/table.js": "sha256-piUGaWv54e50o/2v7ww74yydrQnhGV0dRB9chVItIbQ=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/table.js": "sha256-lZtEzQMmdL7Y6J+TrdKRP9sFsZx0hQRaCjVy3HVN8pU=", + "runtime/chunks/tables-zo8ebTOo.js": "sha256-+LRPZmFKPk0oe8q3HDlfXCXkloBbkRbiFHVHczc3GEs=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-FsyIsB3w0mFPeVNG2Yq+D6/h7aeVKJpEALxaD4j3afY=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/table/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/table/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/table/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/table/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/table/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/table/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/table/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/table/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/table/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/table/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/table/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/table/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/table/runtime/chunks/tables-Cjr1EIJz.js b/packages/ui/dist/copy/table/runtime/chunks/tables-Cjr1EIJz.js deleted file mode 100644 index f82aaf25e..000000000 --- a/packages/ui/dist/copy/table/runtime/chunks/tables-Cjr1EIJz.js +++ /dev/null @@ -1,217 +0,0 @@ -import { c as keyIndex, f as rove, i as all, o as enabled, s as identify } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/tables.js -function table(root, { on }) { - const element = root.querySelector("table"), body = element?.tBodies[0]; - if (!element || !body) return {}; - const rows = () => [...body.rows].filter((row) => !row.matches(".table-empty,.table-loading,.data-table-empty,.data-table-loading,[data-empty],[data-loading]")); - const shown = () => rows().filter((row) => !row.hidden); - const interactive = element.classList.contains("data-table"); - const selectAll = element.querySelector(".data-table-select-all"); - let anchor = null, query = ""; - rows().forEach((row, index) => identify(root, row, `row-${index}`)); - const selected = () => rows().filter((row) => row.getAttribute("aria-selected") === "true"); - const syncSelection = () => { - for (const row of rows()) { - const box = row.querySelector("input[type=\"checkbox\"]"); - if (box) box.checked = row.getAttribute("aria-selected") === "true"; - } - if (selectAll) { - const count = shown().filter((row) => row.getAttribute("aria-selected") === "true").length; - selectAll.setAttribute("aria-checked", count === 0 ? "false" : count === shown().length ? "true" : "mixed"); - } - }; - const reportSelection = () => { - syncSelection(); - root.emit("selection", { ids: selected().map((row) => row.id) }); - }; - const setSelected = (ids) => { - if (!Array.isArray(ids) || ids.some((id) => !rows().some((row) => row.id === id))) throw new RangeError("Selection contains an unknown row"); - rows().forEach((row) => row.setAttribute("aria-selected", String(ids.includes(row.id)))); - syncSelection(); - }; - const sort = (column, direction = "ascending") => { - const headers = [...element.tHead.rows[0].cells]; - if (!Number.isInteger(column) || column < 0 || column >= headers.length || !["ascending", "descending"].includes(direction)) throw new RangeError("Invalid sort column or direction"); - const compare = new Intl.Collator(void 0, { - numeric: true, - sensitivity: "base" - }); - const value = (row) => row.cells[column]?.dataset.sortValue ?? row.cells[column]?.textContent.trim() ?? ""; - rows().sort((a, b) => compare.compare(value(a), value(b)) * (direction === "ascending" ? 1 : -1)).forEach((row) => body.append(row)); - headers.forEach((header) => { - if (header === headers[column]) header.setAttribute("aria-sort", direction); - else header.removeAttribute("aria-sort"); - }); - root.emit("sort", { - column, - direction - }); - }; - const filter = (text) => { - query = String(text ?? ""); - const status = root.querySelector("select[data-status-filter]")?.value ?? "all"; - for (const row of rows()) row.hidden = !row.textContent.toLocaleLowerCase().includes(query.toLocaleLowerCase()) || status !== "all" && row.dataset.status !== status; - const count = shown().length; - const empty = body.querySelector(".table-empty,.data-table-empty,[data-empty]"); - if (empty) empty.hidden = count !== 0 || element.getAttribute("aria-busy") === "true"; - const output = root.querySelector("[data-table-status],.filterable-table-count,.search-field-status"); - if (output) output.textContent = `${count} matching records`; - if (interactive) { - const focused = shown().find((row) => row.tabIndex === 0) ?? shown()[0]; - if (focused) rove(rows(), rows().indexOf(focused), false); - } - syncSelection(); - }; - on(element, "click", (event) => { - const button = event.target.closest(".table-sort,.data-table-sort"); - if (button && enabled(button)) { - const header = button.closest("th"); - sort(header.cellIndex, header.getAttribute("aria-sort") === "ascending" ? "descending" : "ascending"); - } - }); - on(selectAll, "click", () => { - if (!enabled(selectAll)) return; - const checked = selectAll.getAttribute("aria-checked") !== "true"; - shown().forEach((row) => row.setAttribute("aria-selected", String(checked))); - reportSelection(); - }); - on(body, "change", (event) => { - if (event.target.matches("input[type=\"checkbox\"]")) { - event.target.closest("tr").setAttribute("aria-selected", String(event.target.checked)); - reportSelection(); - } - }); - on(body, "keydown", (event) => { - if (!interactive || event.target.matches("input,button,a,select,textarea")) return; - const row = event.target.closest("tr"), options = shown(), index = options.indexOf(row); - if (index < 0) return; - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a") { - event.preventDefault(); - options.forEach((item) => item.setAttribute("aria-selected", "true")); - reportSelection(); - return; - } - if (event.key === " ") { - event.preventDefault(); - if (!selectAll) rows().filter((item) => item !== row).forEach((item) => item.setAttribute("aria-selected", "false")); - row.setAttribute("aria-selected", String(row.getAttribute("aria-selected") !== "true")); - anchor = row; - reportSelection(); - return; - } - if (![ - "ArrowUp", - "ArrowDown", - "Home", - "End" - ].includes(event.key)) return; - event.preventDefault(); - const nextIndex = keyIndex({ - key: event.key, - index, - length: options.length, - wrap: false - }); - const next = rove(options, nextIndex); - if (event.shiftKey && selectAll) { - anchor ??= row; - const start = options.indexOf(anchor); - options.forEach((item, i) => item.setAttribute("aria-selected", String(i >= Math.min(start, nextIndex) && i <= Math.max(start, nextIndex)))); - reportSelection(); - } else if (!selectAll) { - setSelected([next.id]); - reportSelection(); - anchor = next; - } else anchor = next; - }); - const input = root.querySelector("input[type=\"search\"]"); - on(input, "input", () => filter(input.value)); - on(root.querySelector("select[data-status-filter]"), "change", () => filter(input?.value ?? query)); - let drag = null; - const sizes = /* @__PURE__ */ new Map(); - const resize = (header, width) => { - const value = Math.max(64, Math.min(1200, width)); - header.style.width = `${value}px`; - header.style.minWidth = `${value}px`; - sizes.set(header, value); - }; - all(element, ".data-table-resize").forEach((handle) => { - const header = handle.closest("th"); - on(handle, "pointerdown", (event) => { - if (event.button !== 0) return; - event.preventDefault(); - drag = { - header, - x: event.clientX, - width: header.getBoundingClientRect().width, - rtl: getComputedStyle(header).direction === "rtl" - }; - handle.setPointerCapture?.(event.pointerId); - }); - }); - on(root.ownerDocument, "pointermove", (event) => { - if (drag) resize(drag.header, drag.width + (event.clientX - drag.x) * (drag.rtl ? -1 : 1)); - }); - on(root.ownerDocument, "pointerup", () => { - drag = null; - }); - on(root.ownerDocument, "pointercancel", () => { - drag = null; - }); - on(root, "j3w1-action", (event) => { - const match = /^resize:(\d+):(narrow|widen|reset)$/.exec(event.detail.action ?? ""); - if (!match) return; - const header = element.tHead.rows[0].cells[Number(match[1])]; - if (!header) return; - if (match[2] === "reset") { - header.style.removeProperty("width"); - header.style.removeProperty("min-width"); - sizes.delete(header); - } else resize(header, (sizes.get(header) ?? header.getBoundingClientRect().width) + (match[2] === "narrow" ? -24 : 24)); - }); - syncSelection(); - filter(input?.value ?? ""); - return { - sort, - filter, - get selectedIds() { - return selected().map((row) => row.id); - }, - set selectedIds(ids) { - setSelected(ids); - }, - cleanup() { - drag = null; - } - }; -} -function pagination(root, { on }) { - let current = Number(root.querySelector("[aria-current=\"page\"]")?.dataset.page ?? 1); - const setPage = (page) => { - if (!Number.isInteger(page) || page < 1) throw new RangeError("page must be a positive integer"); - current = page; - all(root, "[data-page]").forEach((control) => { - if (Number(control.dataset.page) === page) control.setAttribute("aria-current", "page"); - else control.removeAttribute("aria-current"); - }); - const output = root.querySelector(".pagination-status-current"); - if (output) output.textContent = String(page); - }; - on(root, "click", (event) => { - const control = event.target.closest("[data-page]"); - if (!control || !enabled(control)) return; - const page = Number(control.dataset.page); - setPage(page); - if (!root.emit("page", { page })) event.preventDefault(); - }); - return { - get page() { - return current; - }, - set page(value) { - setPage(value); - } - }; -} -//#endregion -export { table as n, pagination as t }; diff --git a/packages/ui/dist/copy/table/runtime/chunks/tables-zo8ebTOo.js b/packages/ui/dist/copy/table/runtime/chunks/tables-zo8ebTOo.js new file mode 100644 index 000000000..56f7f3dc3 --- /dev/null +++ b/packages/ui/dist/copy/table/runtime/chunks/tables-zo8ebTOo.js @@ -0,0 +1,216 @@ +import { c as keyIndex, f as rove, i as all, o as enabled, s as identify } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/tables.js +function table(root, { on }) { + const element = root.querySelector("table"), body = element?.tBodies[0]; + if (!element || !body) return {}; + const rows = () => [...body.rows].filter((row) => !row.matches(".table-empty,.table-loading,.data-table-empty,.data-table-loading,[data-empty],[data-loading]")); + const shown = () => rows().filter((row) => !row.hidden); + const interactive = element.classList.contains("data-table"); + const selectAll = element.querySelector(".data-table-select-all"); + let anchor = null, query = ""; + rows().forEach((row, index) => identify(root, row, `row-${index}`)); + const selected = () => rows().filter((row) => row.getAttribute("aria-selected") === "true"); + const syncSelection = () => { + for (const row of rows()) { + const box = row.querySelector("input[type=\"checkbox\"]"); + if (box) box.checked = row.getAttribute("aria-selected") === "true"; + } + if (selectAll) { + const count = shown().filter((row) => row.getAttribute("aria-selected") === "true").length; + selectAll.setAttribute("aria-checked", count === 0 ? "false" : count === shown().length ? "true" : "mixed"); + } + }; + const reportSelection = () => { + syncSelection(); + root.emit("selection", { ids: selected().map((row) => row.id) }); + }; + const setSelected = (ids) => { + if (!Array.isArray(ids) || ids.some((id) => !rows().some((row) => row.id === id))) throw new RangeError("Selection contains an unknown row"); + rows().forEach((row) => row.setAttribute("aria-selected", String(ids.includes(row.id)))); + syncSelection(); + }; + const sort = (column, direction = "ascending") => { + const headers = [...element.tHead.rows[0].cells]; + if (!Number.isInteger(column) || column < 0 || column >= headers.length || !["ascending", "descending"].includes(direction)) throw new RangeError("Invalid sort column or direction"); + const compare = new Intl.Collator(void 0, { + numeric: true, + sensitivity: "base" + }); + const value = (row) => row.cells[column]?.dataset.sortValue ?? row.cells[column]?.textContent.trim() ?? ""; + rows().sort((a, b) => compare.compare(value(a), value(b)) * (direction === "ascending" ? 1 : -1)).forEach((row) => body.append(row)); + headers.forEach((header) => { + if (header === headers[column]) header.setAttribute("aria-sort", direction); + else header.removeAttribute("aria-sort"); + }); + root.emit("sort", { + column, + direction + }); + }; + const filter = (text) => { + query = String(text ?? ""); + const status = root.querySelector("select[data-status-filter]")?.value ?? "all"; + for (const row of rows()) row.hidden = !row.textContent.toLocaleLowerCase().includes(query.toLocaleLowerCase()) || status !== "all" && row.dataset.status !== status; + const count = shown().length; + const empty = body.querySelector(".table-empty,.data-table-empty,[data-empty]"); + if (empty) empty.hidden = count !== 0 || element.getAttribute("aria-busy") === "true"; + const output = root.querySelector("[data-table-status],.filterable-table-count,.search-field-status"); + if (output) output.textContent = `${count} matching records`; + if (interactive) { + const focused = shown().find((row) => row.tabIndex === 0) ?? shown()[0]; + if (focused) rove(rows(), rows().indexOf(focused), false); + } + syncSelection(); + }; + on(element, "click", (event) => { + const button = event.target.closest(".table-sort,.data-table-sort"); + if (button && enabled(button)) { + const header = button.closest("th"); + sort(header.cellIndex, header.getAttribute("aria-sort") === "ascending" ? "descending" : "ascending"); + } + }); + on(selectAll, "click", () => { + if (!enabled(selectAll)) return; + const checked = selectAll.getAttribute("aria-checked") !== "true"; + shown().forEach((row) => row.setAttribute("aria-selected", String(checked))); + reportSelection(); + }); + on(body, "change", (event) => { + if (event.target.matches("input[type=\"checkbox\"]")) { + event.target.closest("tr").setAttribute("aria-selected", String(event.target.checked)); + reportSelection(); + } + }); + on(body, "keydown", (event) => { + if (!interactive || event.target.matches("input,button,a,select,textarea")) return; + const row = event.target.closest("tr"), options = shown(), index = options.indexOf(row); + if (index < 0) return; + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a") { + event.preventDefault(); + options.forEach((item) => item.setAttribute("aria-selected", "true")); + reportSelection(); + return; + } + if (event.key === " ") { + event.preventDefault(); + if (!selectAll) rows().filter((item) => item !== row).forEach((item) => item.setAttribute("aria-selected", "false")); + row.setAttribute("aria-selected", String(row.getAttribute("aria-selected") !== "true")); + anchor = row; + reportSelection(); + return; + } + if (![ + "ArrowUp", + "ArrowDown", + "Home", + "End" + ].includes(event.key)) return; + event.preventDefault(); + const nextIndex = keyIndex({ + key: event.key, + index, + length: options.length, + wrap: false + }); + const next = rove(options, nextIndex); + if (event.shiftKey && selectAll) { + anchor ??= row; + const start = options.indexOf(anchor); + options.forEach((item, i) => item.setAttribute("aria-selected", String(i >= Math.min(start, nextIndex) && i <= Math.max(start, nextIndex)))); + reportSelection(); + } else if (!selectAll) { + setSelected([next.id]); + reportSelection(); + anchor = next; + } else anchor = next; + }); + const input = root.querySelector("input[type=\"search\"]"); + on(input, "input", () => filter(input.value)); + on(root.querySelector("select[data-status-filter]"), "change", () => filter(input?.value ?? query)); + let drag = null; + const sizes = /* @__PURE__ */ new Map(); + const resize = (header, width) => { + const value = Math.max(64, Math.min(1200, width)); + header.style.width = `${value}px`; + header.style.minWidth = `${value}px`; + sizes.set(header, value); + }; + all(element, ".data-table-resize").forEach((handle) => { + const header = handle.closest("th"); + on(handle, "pointerdown", (event) => { + if (event.button !== 0) return; + event.preventDefault(); + drag = { + header, + x: event.clientX, + width: header.getBoundingClientRect().width, + rtl: getComputedStyle(header).direction === "rtl" + }; + handle.setPointerCapture?.(event.pointerId); + }); + }); + on(root.ownerDocument, "pointermove", (event) => { + if (drag) resize(drag.header, drag.width + (event.clientX - drag.x) * (drag.rtl ? -1 : 1)); + }); + on(root.ownerDocument, "pointerup", () => { + drag = null; + }); + on(root.ownerDocument, "pointercancel", () => { + drag = null; + }); + on(root, "j3w1-action", (event) => { + const match = /^resize:(\d+):(narrow|widen|reset)$/.exec(event.detail.action ?? ""); + if (!match) return; + const header = element.tHead.rows[0].cells[Number(match[1])]; + if (!header) return; + if (match[2] === "reset") { + header.style.removeProperty("width"); + header.style.removeProperty("min-width"); + sizes.delete(header); + } else resize(header, (sizes.get(header) ?? header.getBoundingClientRect().width) + (match[2] === "narrow" ? -24 : 24)); + }); + syncSelection(); + filter(input?.value ?? ""); + return { + sort, + filter, + get selectedIds() { + return selected().map((row) => row.id); + }, + set selectedIds(ids) { + setSelected(ids); + }, + cleanup() { + drag = null; + } + }; +} +function pagination(root, { on }) { + let current = Number(root.querySelector("[aria-current=\"page\"]")?.dataset.page ?? 1); + const setPage = (page) => { + if (!Number.isInteger(page) || page < 1) throw new RangeError("page must be a positive integer"); + current = page; + all(root, "[data-page]").forEach((control) => { + if (Number(control.dataset.page) === page) control.setAttribute("aria-current", "page"); + else control.removeAttribute("aria-current"); + }); + const output = root.querySelector(".pagination-status-current"); + if (output) output.textContent = String(page); + }; + on(root, "click", (event) => { + const control = event.target.closest("[data-page]"); + if (!control || !enabled(control)) return; + const page = Number(control.dataset.page); + setPage(page); + if (!root.emit("page", { page })) event.preventDefault(); + }); + return { + get page() { + return current; + }, + set page(value) { + setPage(value); + } + }; +} +export { table as n, pagination as t }; diff --git a/packages/ui/dist/copy/table/runtime/components/table.js b/packages/ui/dist/copy/table/runtime/components/table.js index a79632ad4..7d00b4972 100644 --- a/packages/ui/dist/copy/table/runtime/components/table.js +++ b/packages/ui/dist/copy/table/runtime/components/table.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as table } from "../chunks/tables-Cjr1EIJz.js"; -//#region .cache/ui-build/entries/components/table.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as table } from "../chunks/tables-zo8ebTOo.js"; +// .cache/ui-build/entries/components/table.js var J3w1Table = class extends J3w1Element { static componentId = "table"; static version = "4.0.0"; - static implementationId = "sha256-dYinCl3vod1TSMh+SSPtibWEFlVRwhAF7TZ09eviokw="; + static implementationId = "sha256-qzueems4nlIVXm/5XT2r1R4us1YNkmAFjQkeOBgWPiM="; static connect = table; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -17,5 +17,4 @@ var J3w1Table = class extends J3w1Element { return this._api.filter(...args); } }; -//#endregion export { J3w1Table }; diff --git a/packages/ui/dist/copy/table/runtime/register/table.js b/packages/ui/dist/copy/table/runtime/register/table.js index b8eda4f9d..7a9071716 100644 --- a/packages/ui/dist/copy/table/runtime/register/table.js +++ b/packages/ui/dist/copy/table/runtime/register/table.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Table } from "../components/table.js"; -//#region .cache/ui-build/entries/register/table.js +// .cache/ui-build/entries/register/table.js var element = registerElement("j3w1-table", J3w1Table); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/tabs/manifest.json b/packages/ui/dist/copy/tabs/manifest.json index 3e442d814..cb8328bb0 100644 --- a/packages/ui/dist/copy/tabs/manifest.json +++ b/packages/ui/dist/copy/tabs/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/tabs.md", "dependencies": [ "register/tabs.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/tabs.js", - "chunks/navigation-BfNzDYZB.js" + "chunks/navigation-CknoksQ5.js" ], "files": { - "runtime/register/tabs.js": "sha256-l7XwbcEZ8OmMB88/x9pUtN1ecLySUw198ASEleD+hZs=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/tabs.js": "sha256-2AWArhhBdqbiE1BHWeiumCgXyKi847dzv/cMGGfCfuA=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", + "runtime/register/tabs.js": "sha256-vuNpf0Ff4n7Hgx8O4757u2GYg/zd7qZ0qR1yYzIIJME=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/tabs.js": "sha256-EZw8dHljPEIaVDnuxpR0JDUNswrzy2tdcXiSySBYCyo=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-fstv2PtC0k8ABx0bciCb6VX0pPTRl3oa8iGdR+6QR0Y=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/tabs/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/tabs/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/tabs/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/tabs/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/tabs/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/tabs/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/tabs/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/tabs/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/tabs/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/tabs/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/tabs/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/tabs/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/tabs/runtime/chunks/navigation-BfNzDYZB.js b/packages/ui/dist/copy/tabs/runtime/chunks/navigation-BfNzDYZB.js deleted file mode 100644 index db2779553..000000000 --- a/packages/ui/dist/copy/tabs/runtime/chunks/navigation-BfNzDYZB.js +++ /dev/null @@ -1,377 +0,0 @@ -import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/navigation.js -function tabs(root, { on }, listOverride) { - const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); - if (!list) return {}; - const items = () => all(list, "[role=\"tab\"]").filter(enabled); - const select = (id, focus = false) => { - const tab = items().find((item) => item.id === id); - if (!tab) throw new RangeError(`Unknown enabled tab: ${id}`); - all(list, "[role=\"tab\"]").forEach((item) => { - item.setAttribute("aria-selected", String(item === tab)); - item.tabIndex = item === tab ? 0 : -1; - }); - all(root, "[role=\"tabpanel\"]").filter((panel) => all(list, "[role=\"tab\"]").some((tab) => tab.getAttribute("aria-controls") === panel.id)).forEach((panel) => { - panel.hidden = panel.id !== tab.getAttribute("aria-controls"); - if (!panel.hidden && !panel.querySelector("a[href],button,input,select,textarea,[tabindex='0']")) panel.tabIndex = 0; - }); - if (focus) tab.focus(); - return tab; - }; - const activate = (tab) => { - select(tab.id); - root.emit("select", { - id: tab.id, - panelId: tab.getAttribute("aria-controls") - }); - }; - on(list, "click", (event) => { - const tab = event.target.closest("[role=\"tab\"]"); - if (tab && enabled(tab)) activate(tab); - }); - on(list, "keydown", (event) => { - const current = event.target.closest("[role=\"tab\"]"), options = items(); - if (!current) return; - const vertical = list.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(list).direction === "rtl"; - const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", previous = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; - let index = options.indexOf(current); - if (event.key === next) index++; - else if (event.key === previous) index--; - else if (event.key === "Home") index = 0; - else if (event.key === "End") index = options.length - 1; - else if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - activate(current); - return; - } else return; - event.preventDefault(); - const tab = rove(options, index); - if (root.getAttribute("activation") !== "manual") activate(tab); - }); - const initial = items().find((item) => item.getAttribute("aria-selected") === "true") ?? items()[0]; - if (initial) select(initial.id); - return { - select, - get selectedId() { - return list.querySelector("[aria-selected=\"true\"]")?.id ?? ""; - }, - set selectedId(id) { - select(id); - } - }; -} -function toolbar(root, { on }) { - const bar = root.querySelector("[role=\"toolbar\"]"); - if (!bar) return {}; - const controls = () => all(bar, "button,a[href],input,select").filter((node) => enabled(node) && visible(node) && !node.closest("[role=\"menu\"]")); - const initial = controls(); - rove(initial, Math.max(0, initial.findIndex((node) => node.tabIndex === 0)), false); - on(bar, "focusin", (event) => { - if (controls().includes(event.target)) rove(controls(), controls().indexOf(event.target), false); - }); - on(bar, "keydown", (event) => { - if (event.target.matches("input,select,textarea") || event.target.closest("[role=\"menu\"]")) return; - const items = controls(), index = items.indexOf(event.target); - const vertical = bar.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(bar).direction === "rtl"; - const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", prev = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; - if (![ - next, - prev, - "Home", - "End" - ].includes(event.key)) return; - event.preventDefault(); - rove(items, keyIndex({ - key: event.key, - index, - length: items.length, - next, - previous: prev - })); - }); - on(bar, "click", (event) => { - const button = event.target.closest("button[aria-pressed]"); - if (button && enabled(button)) { - button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - root.emit("action", { - action: button.dataset.action ?? button.textContent.trim(), - pressed: button.getAttribute("aria-pressed") === "true" - }); - } - }); - return {}; -} -function disclosure(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button[aria-controls][aria-expanded]"); - if (!button || !enabled(button)) return; - const target = root.querySelector(`#${CSS.escape(button.getAttribute("aria-controls"))}`); - if (!target) return; - const expanded = button.getAttribute("aria-expanded") !== "true"; - button.setAttribute("aria-expanded", String(expanded)); - target.hidden = !expanded; - root.emit("toggle", { - id: target.id, - expanded - }); - }); - const details = root.querySelector("details"); - on(details, "toggle", () => root.emit("toggle", { - id: details.id, - expanded: details.open - })); - return { - get open() { - return details?.open ?? false; - }, - set open(value) { - if (details) details.open = Boolean(value); - } - }; -} -function combobox(root, { on, signal }) { - const input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"); - if (!input || !list) return {}; - identify(root, list, "options"); - input.setAttribute("aria-controls", list.id); - let active = null, notifying = false; - const notify = () => { - notifying = true; - try { - nativeInput(input); - nativeInput(input, "change"); - } finally { - notifying = false; - } - }; - const options = () => all(list, "[role=\"option\"]").filter((node) => enabled(node) && !node.hidden && !node.closest("[role=\"group\"][hidden]")); - all(list, "[role=\"option\"]").forEach((option, index) => identify(root, option, `option-${index}`)); - const setActive = (option) => { - active = option; - all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); - if (option) { - input.setAttribute("aria-activedescendant", option.id); - option.scrollIntoView({ block: "nearest" }); - } else input.removeAttribute("aria-activedescendant"); - }; - const hide = () => { - list.hidden = true; - input.setAttribute("aria-expanded", "false"); - setActive(null); - }; - const filter = (query = input.value) => { - for (const option of all(list, "[role=\"option\"]")) if (enabled(option)) option.hidden = !option.textContent.toLocaleLowerCase().includes(query.toLocaleLowerCase()); - all(list, "[role=\"group\"]").forEach((group) => { - group.hidden = !all(group, "[role=\"option\"]").some((node) => enabled(node) && !node.hidden); - }); - const empty = root.querySelector(".combobox-empty"); - if (empty) { - empty.hidden = options().length !== 0; - empty.classList.toggle("combobox-empty-shown", !empty.hidden); - } - if (!options().includes(active)) setActive(null); - }; - const show = (allOptions = false) => { - if (!enabled(input) || input.readOnly) return; - filter(allOptions ? "" : input.value); - list.hidden = false; - input.setAttribute("aria-expanded", "true"); - place(input, list); - }; - const choose = (option) => { - if (!option || !enabled(option)) return; - input.value = option.dataset.value ?? option.textContent.trim(); - hide(); - notify(); - input.focus(); - }; - on(input, "input", () => { - if (!notifying) { - show(); - announce(root, `${options().length} options available.`); - } - }); - on(input, "keydown", (event) => { - if (event.key === "Tab") { - hide(); - return; - } - if (event.key === "Escape") { - if (!list.hidden) { - hide(); - event.stopPropagation(); - } else if (input.value) { - input.value = ""; - notify(); - event.stopPropagation(); - } - event.preventDefault(); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - hide(); - return; - } - if (["ArrowDown", "ArrowUp"].includes(event.key)) { - event.preventDefault(); - if (list.hidden) show(true); - if (event.altKey) return; - const items = options(), index = active ? items.indexOf(active) : event.key === "ArrowDown" ? -1 : 0; - if (items.length) setActive(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); - } else if (event.key === "Enter" && !list.hidden && active) { - event.preventDefault(); - choose(active); - } - }); - on(list, "pointerdown", (event) => { - if (event.target.closest("[role=\"option\"]")) event.preventDefault(); - }); - on(list, "click", (event) => choose(event.target.closest("[role=\"option\"]"))); - on(root.querySelector(".combobox-toggle"), "click", () => { - list.hidden ? show(true) : hide(); - input.focus(); - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!root.contains(event.target)) hide(); - }); - on(root, "focusout", () => queueMicrotask(() => { - if (!signal.aborted && !root.contains(root.ownerDocument.activeElement)) hide(); - })); - on(root.ownerDocument.defaultView, "resize", () => { - if (!list.hidden) place(input, list); - }); - on(root.ownerDocument, "scroll", (event) => { - if (!list.hidden && !list.contains(event.target)) place(input, list); - }, { capture: true }); - hide(); - return { - show, - hide, - get open() { - return !list.hidden; - }, - set open(value) { - value ? show() : hide(); - }, - get value() { - return input.value; - }, - set value(value) { - input.value = String(value ?? ""); - if (!list.hidden) filter(); - }, - cleanup: hide - }; -} -function menu(root, { on }) { - const trigger = root.querySelector("button[aria-haspopup=\"menu\"]"), main = root.querySelector("[role=\"menu\"]"); - if (!trigger || !main) return {}; - identify(root, main, "menu"); - trigger.setAttribute("aria-controls", main.id); - const lists = all(root, "[role=\"menu\"]"); - const items = (list) => all(list, "[role^=\"menuitem\"]").filter((item) => item.closest("[role=\"menu\"]") === list); - const controller = (list) => all(root, "[aria-controls]").find((node) => node.getAttribute("aria-controls") === list.id); - const closeList = (list) => { - list.hidden = true; - controller(list)?.setAttribute("aria-expanded", "false"); - }; - const hide = (focus = true) => { - lists.forEach(closeList); - if (focus) trigger.focus(); - }; - const showList = (list, button, last = false) => { - list.hidden = false; - button.setAttribute("aria-expanded", "true"); - place(button, list); - rove(items(list), last ? items(list).length - 1 : 0); - }; - const show = () => { - if (enabled(trigger)) showList(main, trigger); - }; - const submenu = (button) => button.hasAttribute("aria-haspopup") ? lists.find((list) => list.id === button.getAttribute("aria-controls")) : null; - const activate = (item) => { - if (!enabled(item)) return; - const child = submenu(item); - if (child) { - showList(child, item); - return; - } - if (item.getAttribute("role") === "menuitemcheckbox") item.setAttribute("aria-checked", String(item.getAttribute("aria-checked") !== "true")); - else if (item.getAttribute("role") === "menuitemradio") items(item.closest("[role=\"menu\"]")).filter((node) => node.getAttribute("role") === "menuitemradio").forEach((node) => node.setAttribute("aria-checked", String(node === item))); - else hide(); - root.emit("action", { - action: item.dataset.action ?? item.textContent.trim(), - checked: item.getAttribute("aria-checked") === "true" - }); - }; - on(trigger, "click", () => main.hidden ? show() : hide()); - on(trigger, "keydown", (event) => { - if (["ArrowDown", "ArrowUp"].includes(event.key) && enabled(trigger)) { - event.preventDefault(); - showList(main, trigger, event.key === "ArrowUp"); - } - }); - on(root, "click", (event) => { - const item = event.target.closest("[role^=\"menuitem\"]"); - if (item) activate(item); - }); - on(root, "keydown", (event) => { - const item = event.target.closest("[role^=\"menuitem\"]"); - if (!item) return; - const list = item.closest("[role=\"menu\"]"), options = items(list), index = options.indexOf(item), rtl = getComputedStyle(list).direction === "rtl"; - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - rove(options, keyIndex({ - key: event.key, - index, - length: options.length - })); - } else if (event.key === "Escape" || event.key === (rtl ? "ArrowRight" : "ArrowLeft") && list !== main) { - event.preventDefault(); - event.stopPropagation(); - if (list !== main) { - closeList(list); - controller(list)?.focus(); - } else hide(); - } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight") && submenu(item)) { - event.preventDefault(); - showList(submenu(item), item); - } else if (event.key === "Tab") hide(); - else if (event.key.length === 1 && /\S/.test(event.key)) { - const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(".menu-label") ?? node).textContent.trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); - if (found) { - event.preventDefault(); - rove(options, options.indexOf(found)); - } - } - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!root.contains(event.target)) hide(false); - }); - on(root.ownerDocument, "focusin", (event) => { - if (!root.contains(event.target)) hide(false); - }); - on(root.ownerDocument.defaultView, "resize", () => lists.filter((list) => !list.hidden).forEach((list) => place(controller(list), list))); - hide(false); - return { - show, - hide, - get open() { - return !main.hidden; - }, - set open(value) { - value ? show() : hide(false); - }, - cleanup() { - hide(false); - } - }; -} -//#endregion -export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/tabs/runtime/chunks/navigation-CknoksQ5.js b/packages/ui/dist/copy/tabs/runtime/chunks/navigation-CknoksQ5.js new file mode 100644 index 000000000..dfd1883e6 --- /dev/null +++ b/packages/ui/dist/copy/tabs/runtime/chunks/navigation-CknoksQ5.js @@ -0,0 +1,376 @@ +import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/navigation.js +function tabs(root, { on }, listOverride) { + const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); + if (!list) return {}; + const items = () => all(list, "[role=\"tab\"]").filter(enabled); + const select = (id, focus = false) => { + const tab = items().find((item) => item.id === id); + if (!tab) throw new RangeError(`Unknown enabled tab: ${id}`); + all(list, "[role=\"tab\"]").forEach((item) => { + item.setAttribute("aria-selected", String(item === tab)); + item.tabIndex = item === tab ? 0 : -1; + }); + all(root, "[role=\"tabpanel\"]").filter((panel) => all(list, "[role=\"tab\"]").some((tab) => tab.getAttribute("aria-controls") === panel.id)).forEach((panel) => { + panel.hidden = panel.id !== tab.getAttribute("aria-controls"); + if (!panel.hidden && !panel.querySelector("a[href],button,input,select,textarea,[tabindex='0']")) panel.tabIndex = 0; + }); + if (focus) tab.focus(); + return tab; + }; + const activate = (tab) => { + select(tab.id); + root.emit("select", { + id: tab.id, + panelId: tab.getAttribute("aria-controls") + }); + }; + on(list, "click", (event) => { + const tab = event.target.closest("[role=\"tab\"]"); + if (tab && enabled(tab)) activate(tab); + }); + on(list, "keydown", (event) => { + const current = event.target.closest("[role=\"tab\"]"), options = items(); + if (!current) return; + const vertical = list.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(list).direction === "rtl"; + const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", previous = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; + let index = options.indexOf(current); + if (event.key === next) index++; + else if (event.key === previous) index--; + else if (event.key === "Home") index = 0; + else if (event.key === "End") index = options.length - 1; + else if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + activate(current); + return; + } else return; + event.preventDefault(); + const tab = rove(options, index); + if (root.getAttribute("activation") !== "manual") activate(tab); + }); + const initial = items().find((item) => item.getAttribute("aria-selected") === "true") ?? items()[0]; + if (initial) select(initial.id); + return { + select, + get selectedId() { + return list.querySelector("[aria-selected=\"true\"]")?.id ?? ""; + }, + set selectedId(id) { + select(id); + } + }; +} +function toolbar(root, { on }) { + const bar = root.querySelector("[role=\"toolbar\"]"); + if (!bar) return {}; + const controls = () => all(bar, "button,a[href],input,select").filter((node) => enabled(node) && visible(node) && !node.closest("[role=\"menu\"]")); + const initial = controls(); + rove(initial, Math.max(0, initial.findIndex((node) => node.tabIndex === 0)), false); + on(bar, "focusin", (event) => { + if (controls().includes(event.target)) rove(controls(), controls().indexOf(event.target), false); + }); + on(bar, "keydown", (event) => { + if (event.target.matches("input,select,textarea") || event.target.closest("[role=\"menu\"]")) return; + const items = controls(), index = items.indexOf(event.target); + const vertical = bar.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(bar).direction === "rtl"; + const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", prev = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; + if (![ + next, + prev, + "Home", + "End" + ].includes(event.key)) return; + event.preventDefault(); + rove(items, keyIndex({ + key: event.key, + index, + length: items.length, + next, + previous: prev + })); + }); + on(bar, "click", (event) => { + const button = event.target.closest("button[aria-pressed]"); + if (button && enabled(button)) { + button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + root.emit("action", { + action: button.dataset.action ?? button.textContent.trim(), + pressed: button.getAttribute("aria-pressed") === "true" + }); + } + }); + return {}; +} +function disclosure(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button[aria-controls][aria-expanded]"); + if (!button || !enabled(button)) return; + const target = root.querySelector(`#${CSS.escape(button.getAttribute("aria-controls"))}`); + if (!target) return; + const expanded = button.getAttribute("aria-expanded") !== "true"; + button.setAttribute("aria-expanded", String(expanded)); + target.hidden = !expanded; + root.emit("toggle", { + id: target.id, + expanded + }); + }); + const details = root.querySelector("details"); + on(details, "toggle", () => root.emit("toggle", { + id: details.id, + expanded: details.open + })); + return { + get open() { + return details?.open ?? false; + }, + set open(value) { + if (details) details.open = Boolean(value); + } + }; +} +function combobox(root, { on, signal }) { + const input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"); + if (!input || !list) return {}; + identify(root, list, "options"); + input.setAttribute("aria-controls", list.id); + let active = null, notifying = false; + const notify = () => { + notifying = true; + try { + nativeInput(input); + nativeInput(input, "change"); + } finally { + notifying = false; + } + }; + const options = () => all(list, "[role=\"option\"]").filter((node) => enabled(node) && !node.hidden && !node.closest("[role=\"group\"][hidden]")); + all(list, "[role=\"option\"]").forEach((option, index) => identify(root, option, `option-${index}`)); + const setActive = (option) => { + active = option; + all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); + if (option) { + input.setAttribute("aria-activedescendant", option.id); + option.scrollIntoView({ block: "nearest" }); + } else input.removeAttribute("aria-activedescendant"); + }; + const hide = () => { + list.hidden = true; + input.setAttribute("aria-expanded", "false"); + setActive(null); + }; + const filter = (query = input.value) => { + for (const option of all(list, "[role=\"option\"]")) if (enabled(option)) option.hidden = !option.textContent.toLocaleLowerCase().includes(query.toLocaleLowerCase()); + all(list, "[role=\"group\"]").forEach((group) => { + group.hidden = !all(group, "[role=\"option\"]").some((node) => enabled(node) && !node.hidden); + }); + const empty = root.querySelector(".combobox-empty"); + if (empty) { + empty.hidden = options().length !== 0; + empty.classList.toggle("combobox-empty-shown", !empty.hidden); + } + if (!options().includes(active)) setActive(null); + }; + const show = (allOptions = false) => { + if (!enabled(input) || input.readOnly) return; + filter(allOptions ? "" : input.value); + list.hidden = false; + input.setAttribute("aria-expanded", "true"); + place(input, list); + }; + const choose = (option) => { + if (!option || !enabled(option)) return; + input.value = option.dataset.value ?? option.textContent.trim(); + hide(); + notify(); + input.focus(); + }; + on(input, "input", () => { + if (!notifying) { + show(); + announce(root, `${options().length} options available.`); + } + }); + on(input, "keydown", (event) => { + if (event.key === "Tab") { + hide(); + return; + } + if (event.key === "Escape") { + if (!list.hidden) { + hide(); + event.stopPropagation(); + } else if (input.value) { + input.value = ""; + notify(); + event.stopPropagation(); + } + event.preventDefault(); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + hide(); + return; + } + if (["ArrowDown", "ArrowUp"].includes(event.key)) { + event.preventDefault(); + if (list.hidden) show(true); + if (event.altKey) return; + const items = options(), index = active ? items.indexOf(active) : event.key === "ArrowDown" ? -1 : 0; + if (items.length) setActive(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); + } else if (event.key === "Enter" && !list.hidden && active) { + event.preventDefault(); + choose(active); + } + }); + on(list, "pointerdown", (event) => { + if (event.target.closest("[role=\"option\"]")) event.preventDefault(); + }); + on(list, "click", (event) => choose(event.target.closest("[role=\"option\"]"))); + on(root.querySelector(".combobox-toggle"), "click", () => { + list.hidden ? show(true) : hide(); + input.focus(); + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!root.contains(event.target)) hide(); + }); + on(root, "focusout", () => queueMicrotask(() => { + if (!signal.aborted && !root.contains(root.ownerDocument.activeElement)) hide(); + })); + on(root.ownerDocument.defaultView, "resize", () => { + if (!list.hidden) place(input, list); + }); + on(root.ownerDocument, "scroll", (event) => { + if (!list.hidden && !list.contains(event.target)) place(input, list); + }, { capture: true }); + hide(); + return { + show, + hide, + get open() { + return !list.hidden; + }, + set open(value) { + value ? show() : hide(); + }, + get value() { + return input.value; + }, + set value(value) { + input.value = String(value ?? ""); + if (!list.hidden) filter(); + }, + cleanup: hide + }; +} +function menu(root, { on }) { + const trigger = root.querySelector("button[aria-haspopup=\"menu\"]"), main = root.querySelector("[role=\"menu\"]"); + if (!trigger || !main) return {}; + identify(root, main, "menu"); + trigger.setAttribute("aria-controls", main.id); + const lists = all(root, "[role=\"menu\"]"); + const items = (list) => all(list, "[role^=\"menuitem\"]").filter((item) => item.closest("[role=\"menu\"]") === list); + const controller = (list) => all(root, "[aria-controls]").find((node) => node.getAttribute("aria-controls") === list.id); + const closeList = (list) => { + list.hidden = true; + controller(list)?.setAttribute("aria-expanded", "false"); + }; + const hide = (focus = true) => { + lists.forEach(closeList); + if (focus) trigger.focus(); + }; + const showList = (list, button, last = false) => { + list.hidden = false; + button.setAttribute("aria-expanded", "true"); + place(button, list); + rove(items(list), last ? items(list).length - 1 : 0); + }; + const show = () => { + if (enabled(trigger)) showList(main, trigger); + }; + const submenu = (button) => button.hasAttribute("aria-haspopup") ? lists.find((list) => list.id === button.getAttribute("aria-controls")) : null; + const activate = (item) => { + if (!enabled(item)) return; + const child = submenu(item); + if (child) { + showList(child, item); + return; + } + if (item.getAttribute("role") === "menuitemcheckbox") item.setAttribute("aria-checked", String(item.getAttribute("aria-checked") !== "true")); + else if (item.getAttribute("role") === "menuitemradio") items(item.closest("[role=\"menu\"]")).filter((node) => node.getAttribute("role") === "menuitemradio").forEach((node) => node.setAttribute("aria-checked", String(node === item))); + else hide(); + root.emit("action", { + action: item.dataset.action ?? item.textContent.trim(), + checked: item.getAttribute("aria-checked") === "true" + }); + }; + on(trigger, "click", () => main.hidden ? show() : hide()); + on(trigger, "keydown", (event) => { + if (["ArrowDown", "ArrowUp"].includes(event.key) && enabled(trigger)) { + event.preventDefault(); + showList(main, trigger, event.key === "ArrowUp"); + } + }); + on(root, "click", (event) => { + const item = event.target.closest("[role^=\"menuitem\"]"); + if (item) activate(item); + }); + on(root, "keydown", (event) => { + const item = event.target.closest("[role^=\"menuitem\"]"); + if (!item) return; + const list = item.closest("[role=\"menu\"]"), options = items(list), index = options.indexOf(item), rtl = getComputedStyle(list).direction === "rtl"; + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + rove(options, keyIndex({ + key: event.key, + index, + length: options.length + })); + } else if (event.key === "Escape" || event.key === (rtl ? "ArrowRight" : "ArrowLeft") && list !== main) { + event.preventDefault(); + event.stopPropagation(); + if (list !== main) { + closeList(list); + controller(list)?.focus(); + } else hide(); + } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight") && submenu(item)) { + event.preventDefault(); + showList(submenu(item), item); + } else if (event.key === "Tab") hide(); + else if (event.key.length === 1 && /\S/.test(event.key)) { + const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(".menu-label") ?? node).textContent.trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); + if (found) { + event.preventDefault(); + rove(options, options.indexOf(found)); + } + } + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!root.contains(event.target)) hide(false); + }); + on(root.ownerDocument, "focusin", (event) => { + if (!root.contains(event.target)) hide(false); + }); + on(root.ownerDocument.defaultView, "resize", () => lists.filter((list) => !list.hidden).forEach((list) => place(controller(list), list))); + hide(false); + return { + show, + hide, + get open() { + return !main.hidden; + }, + set open(value) { + value ? show() : hide(false); + }, + cleanup() { + hide(false); + } + }; +} +export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/tabs/runtime/components/tabs.js b/packages/ui/dist/copy/tabs/runtime/components/tabs.js index 448e73b8b..7538c6ae4 100644 --- a/packages/ui/dist/copy/tabs/runtime/components/tabs.js +++ b/packages/ui/dist/copy/tabs/runtime/components/tabs.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { i as tabs } from "../chunks/navigation-BfNzDYZB.js"; -//#region .cache/ui-build/entries/components/tabs.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { i as tabs } from "../chunks/navigation-CknoksQ5.js"; +// .cache/ui-build/entries/components/tabs.js var J3w1Tabs = class extends J3w1Element { static componentId = "tabs"; static version = "4.0.0"; - static implementationId = "sha256-vWyT4Mr1GxnXVkpNXHK/nd/+0BmdRogsb7+eE6EnQ7A="; + static implementationId = "sha256-264IAmFxjdMOK5kPIhdYJogO9fMeVwBYQiMzGB9GxdU="; static connect = tabs; static upgradeProperties = [ "disabled", @@ -32,5 +32,4 @@ var J3w1Tabs = class extends J3w1Element { }); } }; -//#endregion export { J3w1Tabs }; diff --git a/packages/ui/dist/copy/tabs/runtime/register/tabs.js b/packages/ui/dist/copy/tabs/runtime/register/tabs.js index 218ebc6da..b11b0c4af 100644 --- a/packages/ui/dist/copy/tabs/runtime/register/tabs.js +++ b/packages/ui/dist/copy/tabs/runtime/register/tabs.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Tabs } from "../components/tabs.js"; -//#region .cache/ui-build/entries/register/tabs.js +// .cache/ui-build/entries/register/tabs.js var element = registerElement("j3w1-tabs", J3w1Tabs); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/terminal/manifest.json b/packages/ui/dist/copy/terminal/manifest.json index 7812bd220..512b00a35 100644 --- a/packages/ui/dist/copy/terminal/manifest.json +++ b/packages/ui/dist/copy/terminal/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/terminal.md", "dependencies": [ "register/terminal.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/terminal.js", - "chunks/display-Jm9bAsnb.js" + "chunks/display-l54fb8vw.js" ], "files": { - "runtime/register/terminal.js": "sha256-DtAEqikNcqq/nXccSq0pFsKXxE0BPFgM8N6lScud0Ic=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/terminal.js": "sha256-LBmUT0u6uCLNgKHb3qON4Yl1HjbBCYOByCIC8bGXv2c=", - "runtime/chunks/display-Jm9bAsnb.js": "sha256-qZb1g04piEwY3lfFJwMe+0mXR218ljtVi8mepWxrFv8=", + "runtime/register/terminal.js": "sha256-cqkzu0k247NODxqCLXUjAjT5HVFF/pB9v/cPjdOuIzU=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/terminal.js": "sha256-8gdvRHMk+UXDGa4oKnrV2VH510F4JOGMzVBX9w+nw0E=", + "runtime/chunks/display-l54fb8vw.js": "sha256-xfzo614uMLlSbZc5l+o4vHvrL8yBjQAcV/HJdmPUJ/g=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-qVvYtOU0V9tpTXLiTfobfn2Bv+Ec58ZxsvFuoOO3zqA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/terminal/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/terminal/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/terminal/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/terminal/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/terminal/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/terminal/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/terminal/runtime/chunks/display-Jm9bAsnb.js b/packages/ui/dist/copy/terminal/runtime/chunks/display-Jm9bAsnb.js deleted file mode 100644 index 5bc817830..000000000 --- a/packages/ui/dist/copy/terminal/runtime/chunks/display-Jm9bAsnb.js +++ /dev/null @@ -1,212 +0,0 @@ -import { i as all, l as make, o as enabled } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/display.js -function avatar(root, { on }) { - const frame = root.querySelector(".avatar"), fallback = root.querySelector("[data-avatar-fallback]"); - if (!frame || !fallback) return {}; - let image = frame.querySelector("img"); - if (!image) { - image = make(root, "img", { - alt: "", - hidden: "" - }); - frame.prepend(image); - } - let source = image.getAttribute("src") ?? ""; - const update = (value) => { - source = String(value ?? ""); - image.hidden = true; - fallback.hidden = false; - delete frame.dataset.error; - if (!source) { - image.removeAttribute("src"); - delete frame.dataset.loading; - return; - } - frame.dataset.loading = "true"; - image.src = source; - }; - on(image, "load", () => { - delete frame.dataset.loading; - image.hidden = false; - fallback.hidden = true; - }); - on(image, "error", () => { - delete frame.dataset.loading; - frame.dataset.error = "true"; - image.hidden = true; - fallback.hidden = false; - }); - update(root.getAttribute("src") ?? source); - return { - get src() { - return source; - }, - set src(value) { - update(value); - }, - attributeChanged(name) { - if (name === "src") update(root.getAttribute("src")); - } - }; -} -function chart(root) { - const figure = root.querySelector("figure"), svg = figure?.querySelector("svg"), tbody = figure?.querySelector("tbody"); - if (!figure || !svg || !tbody) return {}; - let values = all(tbody, "tr").map((row) => ({ - label: row.cells[0]?.textContent.trim() ?? "", - value: Number(row.cells[1]?.textContent) - })); - const update = (data) => { - if (!Array.isArray(data) || data.length > 200 || data.some((row) => typeof row.label !== "string" || typeof row.value !== "number" || !Number.isFinite(row.value) || row.value < 0)) throw new TypeError("data must contain at most 200 labelled finite non-negative values"); - values = data.map((row) => ({ - label: row.label, - value: row.value - })); - svg.replaceChildren(); - tbody.replaceChildren(); - const ns = "http://www.w3.org/2000/svg"; - const group = root.ownerDocument.createElementNS(ns, "g"); - group.setAttribute("class", "chart-series"); - svg.append(group); - const width = Math.max(300, values.length * 32), max = Math.max(1, ...values.map((row) => row.value)); - svg.setAttribute("viewBox", `0 0 ${width} 140`); - svg.setAttribute("aria-label", values.length ? values.map((row) => `${row.label}: ${row.value}`).join("; ") : "No data available"); - for (const [index, row] of values.entries()) { - const bar = root.ownerDocument.createElementNS(ns, "rect"), step = (width - 20) / values.length, height = row.value / max * 100; - for (const [name, value] of Object.entries({ - x: 10 + index * step + step * .15, - y: 110 - height, - width: step * .7, - height - })) bar.setAttribute(name, String(value)); - const title = root.ownerDocument.createElementNS(ns, "title"); - title.textContent = `${row.label}: ${row.value}`; - bar.append(title); - group.append(bar); - const tr = make(root, "tr"); - tr.append(make(root, "th", { scope: "row" }, row.label), make(root, "td", {}, row.value)); - tbody.append(tr); - } - svg.toggleAttribute("hidden", !values.length); - const empty = figure.querySelector("[data-chart-empty]"); - if (empty) empty.hidden = values.length !== 0; - }; - return { - get data() { - return values.map((row) => ({ ...row })); - }, - set data(data) { - update(data); - } - }; -} -function editorSearch(root, { on }) { - const input = root.querySelector("[data-query]"), pre = root.querySelector("[data-source]"), status = root.querySelector("[data-search-status]"); - if (!input || !pre) return {}; - let source = pre.textContent, current = -1, matches = []; - const previous = root.querySelector("[data-previous]"), following = root.querySelector("[data-next]"); - const select = (index) => { - current = matches.length ? (index + matches.length) % matches.length : -1; - all(pre, "mark").forEach((mark, i) => mark.toggleAttribute("data-current", i === current)); - if (status) status.textContent = !input.value ? "Enter text to search." : matches.length ? `Match ${current + 1} of ${matches.length}` : "No matches."; - }; - const search = () => { - matches = []; - pre.replaceChildren(); - const query = input.value.toLocaleLowerCase(); - let folded = "", offset = 0; - const starts = [], ends = []; - for (const char of source) { - const text = char.toLocaleLowerCase(); - for (let i = 0; i < text.length; i++) { - starts.push(offset); - ends.push(offset + char.length); - } - folded += text; - offset += char.length; - } - if (query) { - let position = 0; - while ((position = folded.indexOf(query, position)) >= 0) { - const start = starts[position], end = ends[position + query.length - 1]; - if (!matches.length || start >= matches.at(-1).end) matches.push({ - start, - end - }); - position += query.length; - } - } - let cursor = 0; - for (const match of matches) { - pre.append(root.ownerDocument.createTextNode(source.slice(cursor, match.start)), make(root, "mark", {}, source.slice(match.start, match.end))); - cursor = match.end; - } - pre.append(root.ownerDocument.createTextNode(source.slice(cursor))); - if (previous) previous.disabled = !matches.length; - if (following) following.disabled = !matches.length; - select(0); - }; - const next = (direction = 1) => { - if (!matches.length) return; - select(current + (direction < 0 ? -1 : 1)); - all(pre, "mark")[current]?.scrollIntoView({ - block: "nearest", - inline: "nearest" - }); - }; - on(input, "input", search); - on(input, "keydown", (event) => { - if (event.key === "Enter") { - event.preventDefault(); - next(event.shiftKey ? -1 : 1); - } else if (event.key === "Escape" && input.value) { - event.preventDefault(); - event.stopPropagation(); - input.value = ""; - search(); - } - }); - on(previous, "click", () => next(-1)); - on(following, "click", () => next()); - search(); - return { - next, - get source() { - return source; - }, - set source(text) { - source = String(text); - search(); - }, - get query() { - return input.value; - }, - set query(value) { - input.value = String(value); - search(); - }, - get matchCount() { - return matches.length; - } - }; -} -function developerView(root, { on }) { - on(root, "click", (event) => { - const action = event.target.closest("button,[data-action]"); - if (action && enabled(action)) root.emit("action", { action: action.dataset.action ?? action.textContent.trim() }); - }); - return { setText(text) { - let pre = root.querySelector("pre"); - if (!pre) { - pre = make(root, "pre", { - class: "j3w1-readonly-text", - tabindex: "0", - "aria-label": "Read-only text" - }); - root.firstElementChild.replaceChildren(pre); - } - pre.textContent = String(text); - } }; -} -//#endregion -export { editorSearch as i, chart as n, developerView as r, avatar as t }; diff --git a/packages/ui/dist/copy/terminal/runtime/chunks/display-l54fb8vw.js b/packages/ui/dist/copy/terminal/runtime/chunks/display-l54fb8vw.js new file mode 100644 index 000000000..b2f57aaf2 --- /dev/null +++ b/packages/ui/dist/copy/terminal/runtime/chunks/display-l54fb8vw.js @@ -0,0 +1,211 @@ +import { i as all, l as make, o as enabled } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/display.js +function avatar(root, { on }) { + const frame = root.querySelector(".avatar"), fallback = root.querySelector("[data-avatar-fallback]"); + if (!frame || !fallback) return {}; + let image = frame.querySelector("img"); + if (!image) { + image = make(root, "img", { + alt: "", + hidden: "" + }); + frame.prepend(image); + } + let source = image.getAttribute("src") ?? ""; + const update = (value) => { + source = String(value ?? ""); + image.hidden = true; + fallback.hidden = false; + delete frame.dataset.error; + if (!source) { + image.removeAttribute("src"); + delete frame.dataset.loading; + return; + } + frame.dataset.loading = "true"; + image.src = source; + }; + on(image, "load", () => { + delete frame.dataset.loading; + image.hidden = false; + fallback.hidden = true; + }); + on(image, "error", () => { + delete frame.dataset.loading; + frame.dataset.error = "true"; + image.hidden = true; + fallback.hidden = false; + }); + update(root.getAttribute("src") ?? source); + return { + get src() { + return source; + }, + set src(value) { + update(value); + }, + attributeChanged(name) { + if (name === "src") update(root.getAttribute("src")); + } + }; +} +function chart(root) { + const figure = root.querySelector("figure"), svg = figure?.querySelector("svg"), tbody = figure?.querySelector("tbody"); + if (!figure || !svg || !tbody) return {}; + let values = all(tbody, "tr").map((row) => ({ + label: row.cells[0]?.textContent.trim() ?? "", + value: Number(row.cells[1]?.textContent) + })); + const update = (data) => { + if (!Array.isArray(data) || data.length > 200 || data.some((row) => typeof row.label !== "string" || typeof row.value !== "number" || !Number.isFinite(row.value) || row.value < 0)) throw new TypeError("data must contain at most 200 labelled finite non-negative values"); + values = data.map((row) => ({ + label: row.label, + value: row.value + })); + svg.replaceChildren(); + tbody.replaceChildren(); + const ns = "http://www.w3.org/2000/svg"; + const group = root.ownerDocument.createElementNS(ns, "g"); + group.setAttribute("class", "chart-series"); + svg.append(group); + const width = Math.max(300, values.length * 32), max = Math.max(1, ...values.map((row) => row.value)); + svg.setAttribute("viewBox", `0 0 ${width} 140`); + svg.setAttribute("aria-label", values.length ? values.map((row) => `${row.label}: ${row.value}`).join("; ") : "No data available"); + for (const [index, row] of values.entries()) { + const bar = root.ownerDocument.createElementNS(ns, "rect"), step = (width - 20) / values.length, height = row.value / max * 100; + for (const [name, value] of Object.entries({ + x: 10 + index * step + step * .15, + y: 110 - height, + width: step * .7, + height + })) bar.setAttribute(name, String(value)); + const title = root.ownerDocument.createElementNS(ns, "title"); + title.textContent = `${row.label}: ${row.value}`; + bar.append(title); + group.append(bar); + const tr = make(root, "tr"); + tr.append(make(root, "th", { scope: "row" }, row.label), make(root, "td", {}, row.value)); + tbody.append(tr); + } + svg.toggleAttribute("hidden", !values.length); + const empty = figure.querySelector("[data-chart-empty]"); + if (empty) empty.hidden = values.length !== 0; + }; + return { + get data() { + return values.map((row) => ({ ...row })); + }, + set data(data) { + update(data); + } + }; +} +function editorSearch(root, { on }) { + const input = root.querySelector("[data-query]"), pre = root.querySelector("[data-source]"), status = root.querySelector("[data-search-status]"); + if (!input || !pre) return {}; + let source = pre.textContent, current = -1, matches = []; + const previous = root.querySelector("[data-previous]"), following = root.querySelector("[data-next]"); + const select = (index) => { + current = matches.length ? (index + matches.length) % matches.length : -1; + all(pre, "mark").forEach((mark, i) => mark.toggleAttribute("data-current", i === current)); + if (status) status.textContent = !input.value ? "Enter text to search." : matches.length ? `Match ${current + 1} of ${matches.length}` : "No matches."; + }; + const search = () => { + matches = []; + pre.replaceChildren(); + const query = input.value.toLocaleLowerCase(); + let folded = "", offset = 0; + const starts = [], ends = []; + for (const char of source) { + const text = char.toLocaleLowerCase(); + for (let i = 0; i < text.length; i++) { + starts.push(offset); + ends.push(offset + char.length); + } + folded += text; + offset += char.length; + } + if (query) { + let position = 0; + while ((position = folded.indexOf(query, position)) >= 0) { + const start = starts[position], end = ends[position + query.length - 1]; + if (!matches.length || start >= matches.at(-1).end) matches.push({ + start, + end + }); + position += query.length; + } + } + let cursor = 0; + for (const match of matches) { + pre.append(root.ownerDocument.createTextNode(source.slice(cursor, match.start)), make(root, "mark", {}, source.slice(match.start, match.end))); + cursor = match.end; + } + pre.append(root.ownerDocument.createTextNode(source.slice(cursor))); + if (previous) previous.disabled = !matches.length; + if (following) following.disabled = !matches.length; + select(0); + }; + const next = (direction = 1) => { + if (!matches.length) return; + select(current + (direction < 0 ? -1 : 1)); + all(pre, "mark")[current]?.scrollIntoView({ + block: "nearest", + inline: "nearest" + }); + }; + on(input, "input", search); + on(input, "keydown", (event) => { + if (event.key === "Enter") { + event.preventDefault(); + next(event.shiftKey ? -1 : 1); + } else if (event.key === "Escape" && input.value) { + event.preventDefault(); + event.stopPropagation(); + input.value = ""; + search(); + } + }); + on(previous, "click", () => next(-1)); + on(following, "click", () => next()); + search(); + return { + next, + get source() { + return source; + }, + set source(text) { + source = String(text); + search(); + }, + get query() { + return input.value; + }, + set query(value) { + input.value = String(value); + search(); + }, + get matchCount() { + return matches.length; + } + }; +} +function developerView(root, { on }) { + on(root, "click", (event) => { + const action = event.target.closest("button,[data-action]"); + if (action && enabled(action)) root.emit("action", { action: action.dataset.action ?? action.textContent.trim() }); + }); + return { setText(text) { + let pre = root.querySelector("pre"); + if (!pre) { + pre = make(root, "pre", { + class: "j3w1-readonly-text", + tabindex: "0", + "aria-label": "Read-only text" + }); + root.firstElementChild.replaceChildren(pre); + } + pre.textContent = String(text); + } }; +} +export { editorSearch as i, chart as n, developerView as r, avatar as t }; diff --git a/packages/ui/dist/copy/terminal/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/terminal/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/terminal/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/terminal/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/terminal/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/terminal/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/terminal/runtime/components/terminal.js b/packages/ui/dist/copy/terminal/runtime/components/terminal.js index d9c12358a..69f99fbca 100644 --- a/packages/ui/dist/copy/terminal/runtime/components/terminal.js +++ b/packages/ui/dist/copy/terminal/runtime/components/terminal.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as developerView } from "../chunks/display-Jm9bAsnb.js"; -//#region .cache/ui-build/entries/components/terminal.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as developerView } from "../chunks/display-l54fb8vw.js"; +// .cache/ui-build/entries/components/terminal.js var J3w1Terminal = class extends J3w1Element { static componentId = "terminal"; static version = "4.0.0"; - static implementationId = "sha256-vnYvMfEFdH6UbGXHQ5OrfeJTspczt8hiaTWYnXnhlJc="; + static implementationId = "sha256-EaWsX7/hfvpbco1yseFqk/elrH1deuvBKjBPCqnnO2A="; static connect = developerView; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -13,5 +13,4 @@ var J3w1Terminal = class extends J3w1Element { return this._api.setText(...args); } }; -//#endregion export { J3w1Terminal }; diff --git a/packages/ui/dist/copy/terminal/runtime/register/terminal.js b/packages/ui/dist/copy/terminal/runtime/register/terminal.js index 0f41964d0..622a5164a 100644 --- a/packages/ui/dist/copy/terminal/runtime/register/terminal.js +++ b/packages/ui/dist/copy/terminal/runtime/register/terminal.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Terminal } from "../components/terminal.js"; -//#region .cache/ui-build/entries/register/terminal.js +// .cache/ui-build/entries/register/terminal.js var element = registerElement("j3w1-terminal", J3w1Terminal); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/text-field/manifest.json b/packages/ui/dist/copy/text-field/manifest.json index 988c0f449..8d3fe79ad 100644 --- a/packages/ui/dist/copy/text-field/manifest.json +++ b/packages/ui/dist/copy/text-field/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/text-field.md", "dependencies": [ "register/text-field.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/text-field.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/text-field.js": "sha256-gmqyzVDUD/VCnOF5nDRA0n1F4I7q7lE02AdZeBCFrUk=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/text-field.js": "sha256-4c47ee0iFW2YWW+dVR1PBSJMwOOa5rmKhJSalXzm+Zo=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/text-field.js": "sha256-MdEo5+b/G/mM5hz7fcSDyO//Htiapsit78fIYEhm59k=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/text-field.js": "sha256-qPB+cDkHzpm0/dIb3MLq2aw8aYuTw8eeiXDYfuaVwwE=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-e3OAwau9F97LYarFVXWbKIfnS2R8w0n/O47hHa1tjco=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/text-field/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/text-field/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/text-field/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/text-field/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/text-field/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/text-field/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/text-field/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/text-field/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/text-field/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/text-field/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/text-field/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/text-field/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/text-field/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/text-field/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/text-field/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/text-field/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/text-field/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/text-field/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/text-field/runtime/components/text-field.js b/packages/ui/dist/copy/text-field/runtime/components/text-field.js index 5f6946538..bfc3476ad 100644 --- a/packages/ui/dist/copy/text-field/runtime/components/text-field.js +++ b/packages/ui/dist/copy/text-field/runtime/components/text-field.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/text-field.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/text-field.js var J3w1TextField = class extends J3w1Element { static componentId = "text-field"; static version = "4.0.0"; - static implementationId = "sha256-k06i0LBPa/oPe2VNmxbJkBzisp1zcAENq3MeVnKZzAo="; + static implementationId = "sha256-/LAwaTyhlpYQI8437cVvaHxrflDBWGv7PN7EEfW2aSE="; static connect = fields; static upgradeProperties = [ "disabled", @@ -31,5 +31,4 @@ var J3w1TextField = class extends J3w1Element { return this._api.stepBy(...args); } }; -//#endregion export { J3w1TextField }; diff --git a/packages/ui/dist/copy/text-field/runtime/register/text-field.js b/packages/ui/dist/copy/text-field/runtime/register/text-field.js index 01007e107..53e0c005f 100644 --- a/packages/ui/dist/copy/text-field/runtime/register/text-field.js +++ b/packages/ui/dist/copy/text-field/runtime/register/text-field.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1TextField } from "../components/text-field.js"; -//#region .cache/ui-build/entries/register/text-field.js +// .cache/ui-build/entries/register/text-field.js var element = registerElement("j3w1-text-field", J3w1TextField); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/textarea/manifest.json b/packages/ui/dist/copy/textarea/manifest.json index af6e1c94e..abae5c724 100644 --- a/packages/ui/dist/copy/textarea/manifest.json +++ b/packages/ui/dist/copy/textarea/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/textarea.md", "dependencies": [ "register/textarea.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/textarea.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/textarea.js": "sha256-OGjZrk++zzTI91HXv7chKm86kRb5xICVcoOOdMidF2g=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/textarea.js": "sha256-pi3Oj4itdBVYU/EaRSZ64BqAEsBdeUH4LCG2kwSUKfw=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/textarea.js": "sha256-kKiC3PacJzn+IIdz6JEkzMEOawMA3/ge/FCAnqsmWPM=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/textarea.js": "sha256-/Z89vI8KLV9ojTcxZPRnV0C0nGRVDX3vFp0LRy/BR4M=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-VB3HAgE+H7HB6tMee0dbFbD3l1YmgFtsLiCzLuvGZzs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/textarea/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/textarea/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/textarea/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/textarea/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/textarea/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/textarea/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/textarea/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/textarea/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/textarea/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/textarea/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/textarea/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/textarea/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/textarea/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/textarea/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/textarea/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/textarea/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/textarea/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/textarea/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/textarea/runtime/components/textarea.js b/packages/ui/dist/copy/textarea/runtime/components/textarea.js index 850762b41..bb600b3d9 100644 --- a/packages/ui/dist/copy/textarea/runtime/components/textarea.js +++ b/packages/ui/dist/copy/textarea/runtime/components/textarea.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/textarea.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/textarea.js var J3w1Textarea = class extends J3w1Element { static componentId = "textarea"; static version = "4.0.0"; - static implementationId = "sha256-BoVEmVsZUWTLPVMKc4WLoQfNpjGc4Wy8j7o7zHck1uQ="; + static implementationId = "sha256-N6gpTKdWZilxDYkj8So4jkvfInVXt3HlRRVVtkRkqsM="; static connect = fields; static upgradeProperties = [ "disabled", @@ -27,5 +27,4 @@ var J3w1Textarea = class extends J3w1Element { return this._api.clear(...args); } }; -//#endregion export { J3w1Textarea }; diff --git a/packages/ui/dist/copy/textarea/runtime/register/textarea.js b/packages/ui/dist/copy/textarea/runtime/register/textarea.js index 2e9a5db69..36b7b5d3c 100644 --- a/packages/ui/dist/copy/textarea/runtime/register/textarea.js +++ b/packages/ui/dist/copy/textarea/runtime/register/textarea.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Textarea } from "../components/textarea.js"; -//#region .cache/ui-build/entries/register/textarea.js +// .cache/ui-build/entries/register/textarea.js var element = registerElement("j3w1-textarea", J3w1Textarea); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/time-picker/manifest.json b/packages/ui/dist/copy/time-picker/manifest.json index da58c6e8f..46a44c252 100644 --- a/packages/ui/dist/copy/time-picker/manifest.json +++ b/packages/ui/dist/copy/time-picker/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/time-picker.md", "dependencies": [ "register/time-picker.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/time-picker.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/time-picker.js": "sha256-Y3N2tnRzLjdmpYzxx3rCbl+joREEqSwDzaFTVHIudjM=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/time-picker.js": "sha256-8R5WT2w1+ieYWJkWby33LbGCbBuQiWHFaETY+vXANpc=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/time-picker.js": "sha256-OfeHc50DC0CCpDG6HtsOTCBHorWppUtU1rY98SCCb/c=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/time-picker.js": "sha256-2p3tnHMSvEtUF5fupvSa83suSSNzx7lNWyogBq+VDw4=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-fySG8CnltTPsU5F0+8Cbt+YUVtEAU2AAkDFqezc416I=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/time-picker/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/time-picker/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/time-picker/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/time-picker/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/time-picker/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/time-picker/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/time-picker/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/time-picker/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/time-picker/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/time-picker/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/time-picker/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/time-picker/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/time-picker/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/time-picker/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/time-picker/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/time-picker/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/time-picker/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/time-picker/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/time-picker/runtime/components/time-picker.js b/packages/ui/dist/copy/time-picker/runtime/components/time-picker.js index 182becce4..d34ef01e1 100644 --- a/packages/ui/dist/copy/time-picker/runtime/components/time-picker.js +++ b/packages/ui/dist/copy/time-picker/runtime/components/time-picker.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as fields } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/time-picker.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as fields } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/time-picker.js var J3w1TimePicker = class extends J3w1Element { static componentId = "time-picker"; static version = "4.0.0"; - static implementationId = "sha256-IYFVpO+yyMztyk5IQgkfuuyrieY/xyLgcisHM1D02DA="; + static implementationId = "sha256-EhUMFyx8J5zlwkM0jR2I+gtvKReYxpzngJ3xpfIzS7E="; static connect = fields; static upgradeProperties = [ "disabled", @@ -27,5 +27,4 @@ var J3w1TimePicker = class extends J3w1Element { return this._api.clear(...args); } }; -//#endregion export { J3w1TimePicker }; diff --git a/packages/ui/dist/copy/time-picker/runtime/register/time-picker.js b/packages/ui/dist/copy/time-picker/runtime/register/time-picker.js index f69ab0f23..4e31ec582 100644 --- a/packages/ui/dist/copy/time-picker/runtime/register/time-picker.js +++ b/packages/ui/dist/copy/time-picker/runtime/register/time-picker.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1TimePicker } from "../components/time-picker.js"; -//#region .cache/ui-build/entries/register/time-picker.js +// .cache/ui-build/entries/register/time-picker.js var element = registerElement("j3w1-time-picker", J3w1TimePicker); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/timeline/manifest.json b/packages/ui/dist/copy/timeline/manifest.json index 514f2712b..eb59c1c1b 100644 --- a/packages/ui/dist/copy/timeline/manifest.json +++ b/packages/ui/dist/copy/timeline/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/timeline.md", "dependencies": [ "register/timeline.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/timeline.js", - "chunks/native-BjBt1sUh.js" + "chunks/native-D61761VL.js" ], "files": { - "runtime/register/timeline.js": "sha256-uXCGuHnZsZSnhQMl00/o559cmYMJo79IrZ1j4ZNySb0=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/timeline.js": "sha256-qOO9Ngp7Zj87zq3HaROWETcECMB8hz5rgR4ryNoEh34=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/timeline.js": "sha256-r6uPm82JiaBwzIf1SK006gw7WwY6ufiNxUnMnb5O4sA=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/timeline.js": "sha256-eRmNcK1XzdBB4hBBB4W6Hj6xUS2nNVfEv3BXw5hMJ3Q=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-Af6JACyiwzdqViRAgkXYbYmHSNOZKW+lyj7uVYBMHkc=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/timeline/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/timeline/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/timeline/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/timeline/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/timeline/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/timeline/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/timeline/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/timeline/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/timeline/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/timeline/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/timeline/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/timeline/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/timeline/runtime/chunks/native-BjBt1sUh.js b/packages/ui/dist/copy/timeline/runtime/chunks/native-BjBt1sUh.js deleted file mode 100644 index 032f76c74..000000000 --- a/packages/ui/dist/copy/timeline/runtime/chunks/native-BjBt1sUh.js +++ /dev/null @@ -1,289 +0,0 @@ -import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/native.js -function content() { - return {}; -} -function actions(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; - if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - if (!root.emit("action", { - action: button.dataset.action ?? button.value ?? "", - pressed: button.getAttribute("aria-pressed") === "true" - })) event.preventDefault(); - }); - return {}; -} -function fields(root, { on, signal }) { - const input = root.querySelector("input,textarea,select"); - if (!input) return {}; - if (input.tagName === "SELECT") { - const choice = mountChoice(input); - return { - get values() { - return [...input.selectedOptions].map((option) => option.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const selected = new Set(values.map(String)); - [...input.options].forEach((option) => { - option.selected = selected.has(option.value); - }); - choice.sync(); - }, - clear() { - if (input.matches(":disabled")) return; - input.value = ""; - choice.sync(); - nativeInput(input); - nativeInput(input, "change"); - }, - attributeChanged: choice.sync, - valueChanged: choice.sync, - cleanup: choice.destroy - }; - } - const count = root.querySelector(".textarea-count,output"); - const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); - const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); - const sync = () => { - if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; - clearButtons.forEach((button) => { - button.hidden = !input.value; - button.disabled = input.disabled || input.readOnly; - }); - temporal.forEach((control) => control.sync()); - }; - const change = () => { - sync(); - nativeInput(input); - nativeInput(input, "change"); - }; - const clear = () => { - if (!enabled(input) || input.readOnly) return; - input.value = ""; - change(); - input.focus(); - }; - clearButtons.forEach((button) => on(button, "click", clear)); - const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); - if (reveal) on(reveal, "click", () => { - if (!enabled(input)) return; - const showing = input.type === "password"; - input.type = showing ? "text" : "password"; - reveal.setAttribute("aria-pressed", String(showing)); - reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); - }); - const step = (direction) => { - if (!enabled(input) || input.readOnly || input.type !== "number") return; - direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); - change(); - }; - all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); - on(input, "keydown", (event) => { - if (event.key === "Escape" && input.type === "search" && input.value) { - event.preventDefault(); - event.stopPropagation(); - clear(); - } - if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { - event.preventDefault(); - step(event.key === "ArrowUp" ? 10 : -10); - } - }); - const dates = all(root, "input[type=\"date\"]"); - const validateRange = () => { - if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); - }; - on(root, "input", () => { - sync(); - validateRange(); - }); - on(root.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!signal.aborted && !event.defaultPrevented) { - sync(); - validateRange(); - } - }); - }, { capture: true }); - sync(); - validateRange(); - return { - clear, - stepBy: step, - get indeterminate() { - return Boolean(input.indeterminate); - }, - set indeterminate(value) { - if (input.type === "checkbox") input.indeterminate = Boolean(value); - }, - get values() { - return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); - }, - set values(values) { - if (!Array.isArray(values)) throw new TypeError("values must be an array"); - const chosen = new Set(values.map(String)); - if (input.multiple) [...input.options].forEach((option) => { - option.selected = chosen.has(option.value); - }); - else all(root, "input[type=\"checkbox\"]").forEach((box) => { - box.checked = chosen.has(box.value); - }); - }, - attributeChanged() { - sync(); - validateRange(); - }, - valueChanged() { - sync(); - validateRange(); - }, - cleanup() { - temporal.forEach((control) => control.destroy()); - } - }; -} -function switchControl(root, { on, signal }) { - const button = root.querySelector("[role=\"switch\"]"); - if (!button) return {}; - const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; - let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; - button.dataset.defaultChecked = String(defaultChecked); - let checked = initial; - let successful = root.querySelector("input[data-switch-value]"); - if (!successful) { - successful = make(root, "input", { - type: "hidden", - "data-switch-value": "" - }); - root.append(successful); - } - const sync = () => { - button.setAttribute("aria-checked", String(checked)); - successful.name = root.getAttribute("name") ?? ""; - successful.value = root.getAttribute("value") ?? "on"; - successful.disabled = !checked || !enabled(button); - }; - on(button, "click", () => { - if (enabled(button)) { - checked = !checked; - sync(); - root.emit("change", { - checked, - value: successful.value, - name: successful.name - }); - } - }); - on(button.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) { - checked = defaultChecked; - sync(); - } - })); - sync(); - return { - get checked() { - return checked; - }, - set checked(value) { - checked = Boolean(value); - sync(); - }, - attributeChanged(name) { - if (name === "checked") { - defaultChecked = checked = root.hasAttribute("checked"); - button.dataset.defaultChecked = String(defaultChecked); - } - sync(); - } - }; -} -function fileInput(root, { on, signal }) { - const input = root.querySelector("input[type=\"file\"]"); - if (!input) return {}; - let list = root.querySelector(".file-input-list"); - if (!list) { - list = make(root, "ul", { - class: "file-input-list", - "aria-label": "Chosen files" - }); - root.append(list); - } - const status = root.querySelector(".file-input-status"); - const draw = () => { - list.replaceChildren(); - const files = [...input.files]; - if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; - for (const [index, file] of files.entries()) { - const item = make(root, "li", { class: "file-input-item" }); - item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); - const remove = make(root, "button", { - type: "button", - class: "file-input-remove", - "aria-label": `Remove ${file.name}`, - "data-remove-index": index - }, "✕"); - remove.disabled = input.disabled; - item.append(remove); - list.append(item); - } - }; - const assign = (files) => { - if (!enabled(input)) return; - const transfer = new DataTransfer(); - for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); - input.files = transfer.files; - draw(); - nativeInput(input); - nativeInput(input, "change"); - }; - on(list, "click", (event) => { - const button = event.target.closest("[data-remove-index]"); - if (!button || !enabled(button)) return; - const index = Number(button.dataset.removeIndex); - assign([...input.files].filter((_, i) => i !== index)); - (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); - }); - on(list, "keydown", (event) => { - if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { - event.preventDefault(); - event.target.click(); - } - }); - const zone = root.querySelector(".file-input-zone"); - if (zone) { - on(zone, "dragover", (event) => { - if (enabled(input)) { - event.preventDefault(); - zone.dataset.dragging = "true"; - } - }); - on(zone, "dragleave", () => { - delete zone.dataset.dragging; - }); - on(zone, "drop", (event) => { - event.preventDefault(); - delete zone.dataset.dragging; - assign([...event.dataTransfer.files]); - }); - } - on(input, "change", draw); - on(input.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - get files() { - return [...input.files]; - }, - clear() { - assign([]); - }, - attributeChanged: draw - }; -} -//#endregion -export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/timeline/runtime/chunks/native-D61761VL.js b/packages/ui/dist/copy/timeline/runtime/chunks/native-D61761VL.js new file mode 100644 index 000000000..d73311256 --- /dev/null +++ b/packages/ui/dist/copy/timeline/runtime/chunks/native-D61761VL.js @@ -0,0 +1,288 @@ +import { i as all, l as make, n as mountChoice, o as enabled, r as mountTemporal, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/native.js +function content() { + return {}; +} +function actions(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button) || button.closest("[data-j3w1-component]") !== root) return; + if (button.hasAttribute("aria-pressed")) button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + if (!root.emit("action", { + action: button.dataset.action ?? button.value ?? "", + pressed: button.getAttribute("aria-pressed") === "true" + })) event.preventDefault(); + }); + return {}; +} +function fields(root, { on, signal }) { + const input = root.querySelector("input,textarea,select"); + if (!input) return {}; + if (input.tagName === "SELECT") { + const choice = mountChoice(input); + return { + get values() { + return [...input.selectedOptions].map((option) => option.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const selected = new Set(values.map(String)); + [...input.options].forEach((option) => { + option.selected = selected.has(option.value); + }); + choice.sync(); + }, + clear() { + if (input.matches(":disabled")) return; + input.value = ""; + choice.sync(); + nativeInput(input); + nativeInput(input, "change"); + }, + attributeChanged: choice.sync, + valueChanged: choice.sync, + cleanup: choice.destroy + }; + } + const count = root.querySelector(".textarea-count,output"); + const temporal = all(root, "input[type=\"date\"],input[type=\"time\"]").map(mountTemporal); + const clearButtons = all(root, "[data-clear],.search-field-clear,button[aria-label^=\"Clear\"]"); + const sync = () => { + if (count) count.textContent = input.type === "range" ? input.value : `${input.value.length}${input.maxLength > 0 ? ` / ${input.maxLength}` : ""}`; + clearButtons.forEach((button) => { + button.hidden = !input.value; + button.disabled = input.disabled || input.readOnly; + }); + temporal.forEach((control) => control.sync()); + }; + const change = () => { + sync(); + nativeInput(input); + nativeInput(input, "change"); + }; + const clear = () => { + if (!enabled(input) || input.readOnly) return; + input.value = ""; + change(); + input.focus(); + }; + clearButtons.forEach((button) => on(button, "click", clear)); + const reveal = root.querySelector("[data-reveal],button[aria-label*=\"password\"]"); + if (reveal) on(reveal, "click", () => { + if (!enabled(input)) return; + const showing = input.type === "password"; + input.type = showing ? "text" : "password"; + reveal.setAttribute("aria-pressed", String(showing)); + reveal.setAttribute("aria-label", showing ? "Hide password" : "Show password"); + }); + const step = (direction) => { + if (!enabled(input) || input.readOnly || input.type !== "number") return; + direction > 0 ? input.stepUp(direction) : input.stepDown(-direction); + change(); + }; + all(root, "[data-step],button[aria-label^=\"Increase\"],button[aria-label^=\"Decrease\"]").forEach((button) => on(button, "click", () => step(Number(button.dataset.step ?? (button.getAttribute("aria-label").startsWith("Decrease") ? -1 : 1))))); + on(input, "keydown", (event) => { + if (event.key === "Escape" && input.type === "search" && input.value) { + event.preventDefault(); + event.stopPropagation(); + clear(); + } + if (input.type === "number" && event.shiftKey && ["ArrowUp", "ArrowDown"].includes(event.key)) { + event.preventDefault(); + step(event.key === "ArrowUp" ? 10 : -10); + } + }); + const dates = all(root, "input[type=\"date\"]"); + const validateRange = () => { + if (dates.length === 2) dates[1].setCustomValidity(dates[0].value && dates[1].value && dates[1].value < dates[0].value ? "End date must be on or after the start date." : ""); + }; + on(root, "input", () => { + sync(); + validateRange(); + }); + on(root.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!signal.aborted && !event.defaultPrevented) { + sync(); + validateRange(); + } + }); + }, { capture: true }); + sync(); + validateRange(); + return { + clear, + stepBy: step, + get indeterminate() { + return Boolean(input.indeterminate); + }, + set indeterminate(value) { + if (input.type === "checkbox") input.indeterminate = Boolean(value); + }, + get values() { + return input.multiple ? [...input.selectedOptions].map((option) => option.value) : all(root, "input[type=\"checkbox\"]:checked").map((box) => box.value); + }, + set values(values) { + if (!Array.isArray(values)) throw new TypeError("values must be an array"); + const chosen = new Set(values.map(String)); + if (input.multiple) [...input.options].forEach((option) => { + option.selected = chosen.has(option.value); + }); + else all(root, "input[type=\"checkbox\"]").forEach((box) => { + box.checked = chosen.has(box.value); + }); + }, + attributeChanged() { + sync(); + validateRange(); + }, + valueChanged() { + sync(); + validateRange(); + }, + cleanup() { + temporal.forEach((control) => control.destroy()); + } + }; +} +function switchControl(root, { on, signal }) { + const button = root.querySelector("[role=\"switch\"]"); + if (!button) return {}; + const initial = root.hasAttribute("checked") || button.getAttribute("aria-checked") === "true"; + let defaultChecked = button.dataset.defaultChecked === void 0 ? initial : button.dataset.defaultChecked === "true"; + button.dataset.defaultChecked = String(defaultChecked); + let checked = initial; + let successful = root.querySelector("input[data-switch-value]"); + if (!successful) { + successful = make(root, "input", { + type: "hidden", + "data-switch-value": "" + }); + root.append(successful); + } + const sync = () => { + button.setAttribute("aria-checked", String(checked)); + successful.name = root.getAttribute("name") ?? ""; + successful.value = root.getAttribute("value") ?? "on"; + successful.disabled = !checked || !enabled(button); + }; + on(button, "click", () => { + if (enabled(button)) { + checked = !checked; + sync(); + root.emit("change", { + checked, + value: successful.value, + name: successful.name + }); + } + }); + on(button.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) { + checked = defaultChecked; + sync(); + } + })); + sync(); + return { + get checked() { + return checked; + }, + set checked(value) { + checked = Boolean(value); + sync(); + }, + attributeChanged(name) { + if (name === "checked") { + defaultChecked = checked = root.hasAttribute("checked"); + button.dataset.defaultChecked = String(defaultChecked); + } + sync(); + } + }; +} +function fileInput(root, { on, signal }) { + const input = root.querySelector("input[type=\"file\"]"); + if (!input) return {}; + let list = root.querySelector(".file-input-list"); + if (!list) { + list = make(root, "ul", { + class: "file-input-list", + "aria-label": "Chosen files" + }); + root.append(list); + } + const status = root.querySelector(".file-input-status"); + const draw = () => { + list.replaceChildren(); + const files = [...input.files]; + if (status) status.textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"} chosen` : "No file chosen"; + for (const [index, file] of files.entries()) { + const item = make(root, "li", { class: "file-input-item" }); + item.append(make(root, "span", { class: "file-input-name" }, file.name), make(root, "span", { class: "file-input-size" }, `${file.size} bytes`)); + const remove = make(root, "button", { + type: "button", + class: "file-input-remove", + "aria-label": `Remove ${file.name}`, + "data-remove-index": index + }, "✕"); + remove.disabled = input.disabled; + item.append(remove); + list.append(item); + } + }; + const assign = (files) => { + if (!enabled(input)) return; + const transfer = new DataTransfer(); + for (const file of input.multiple ? files : files.slice(0, 1)) transfer.items.add(file); + input.files = transfer.files; + draw(); + nativeInput(input); + nativeInput(input, "change"); + }; + on(list, "click", (event) => { + const button = event.target.closest("[data-remove-index]"); + if (!button || !enabled(button)) return; + const index = Number(button.dataset.removeIndex); + assign([...input.files].filter((_, i) => i !== index)); + (list.querySelectorAll("button")[Math.min(index, input.files.length - 1)] ?? input).focus(); + }); + on(list, "keydown", (event) => { + if (["Delete", "Backspace"].includes(event.key) && event.target.matches("button")) { + event.preventDefault(); + event.target.click(); + } + }); + const zone = root.querySelector(".file-input-zone"); + if (zone) { + on(zone, "dragover", (event) => { + if (enabled(input)) { + event.preventDefault(); + zone.dataset.dragging = "true"; + } + }); + on(zone, "dragleave", () => { + delete zone.dataset.dragging; + }); + on(zone, "drop", (event) => { + event.preventDefault(); + delete zone.dataset.dragging; + assign([...event.dataTransfer.files]); + }); + } + on(input, "change", draw); + on(input.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + get files() { + return [...input.files]; + }, + clear() { + assign([]); + }, + attributeChanged: draw + }; +} +export { switchControl as a, fileInput as i, content as n, fields as r, actions as t }; diff --git a/packages/ui/dist/copy/timeline/runtime/components/timeline.js b/packages/ui/dist/copy/timeline/runtime/components/timeline.js index b5e0249ea..749602508 100644 --- a/packages/ui/dist/copy/timeline/runtime/components/timeline.js +++ b/packages/ui/dist/copy/timeline/runtime/components/timeline.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as content } from "../chunks/native-BjBt1sUh.js"; -//#region .cache/ui-build/entries/components/timeline.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as content } from "../chunks/native-D61761VL.js"; +// .cache/ui-build/entries/components/timeline.js var J3w1Timeline = class extends J3w1Element { static componentId = "timeline"; static version = "4.0.0"; - static implementationId = "sha256-AeDLITSMVmcqyJwXO1iz+6eWe9/9kWYL6lepUxS5ZtU="; + static implementationId = "sha256-p2Koxe1oSG3IRYJ6sKk+H6cBn3AC7H+5Goi4No5rZ+Y="; static connect = content; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Timeline }; diff --git a/packages/ui/dist/copy/timeline/runtime/register/timeline.js b/packages/ui/dist/copy/timeline/runtime/register/timeline.js index 6b8f4b354..53dbbcc7b 100644 --- a/packages/ui/dist/copy/timeline/runtime/register/timeline.js +++ b/packages/ui/dist/copy/timeline/runtime/register/timeline.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Timeline } from "../components/timeline.js"; -//#region .cache/ui-build/entries/register/timeline.js +// .cache/ui-build/entries/register/timeline.js var element = registerElement("j3w1-timeline", J3w1Timeline); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/toast/manifest.json b/packages/ui/dist/copy/toast/manifest.json index 70549a7b8..c9445cf38 100644 --- a/packages/ui/dist/copy/toast/manifest.json +++ b/packages/ui/dist/copy/toast/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/toast.md", "dependencies": [ "register/toast.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/toast.js", - "chunks/overlays-BwgpF4jI.js" + "chunks/overlays-BW66WXLm.js" ], "files": { - "runtime/register/toast.js": "sha256-3boFTJqHNwJ4he43NpdsZK8ttLeqvz9HMoUtwFjVwtk=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/toast.js": "sha256-1dFBmSju1EG6JDJzOQqZ+RK4CzRzFpUX0heoc0jbyF8=", - "runtime/chunks/overlays-BwgpF4jI.js": "sha256-NAd99OT4kDsFp8IHscKRus2jY6XRsq+GMzplWbJsY4U=", + "runtime/register/toast.js": "sha256-T5DYWi24uZw+rG6LBmJOUq8W1SaQkxZXz7JNdRbEUfM=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/toast.js": "sha256-XsXKDN1g1p/dUFMGbcOZtPxqPsa1wVAqjrBDVX0e0jI=", + "runtime/chunks/overlays-BW66WXLm.js": "sha256-Z9etmUpuDuykKbJkriLMz8iiYnOP9uMUAshKwoHc1I8=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-uDOVAGMFD+o43PgFLYIr3brOp1t4nrDGrE8jaKF7S2U=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/toast/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/toast/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/toast/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/toast/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/toast/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/toast/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/toast/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/toast/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/toast/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/toast/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/toast/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/toast/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/toast/runtime/chunks/overlays-BW66WXLm.js b/packages/ui/dist/copy/toast/runtime/chunks/overlays-BW66WXLm.js new file mode 100644 index 000000000..d05c73b46 --- /dev/null +++ b/packages/ui/dist/copy/toast/runtime/chunks/overlays-BW66WXLm.js @@ -0,0 +1,244 @@ +import { d as place, i as all, o as enabled, s as identify } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/overlays.js +function modal(root, { on }) { + const dialog = root.querySelector("dialog"); + if (!dialog) return {}; + let opener = null; + const show = (trigger = root.ownerDocument.activeElement) => { + if (dialog.open || root.hasAttribute("disabled")) return; + opener = trigger; + dialog.showModal(); + (dialog.querySelector("[autofocus]") ?? dialog.querySelector("button:not(.dialog-button-destructive)"))?.focus(); + root.emit("open", {}); + }; + const close = (value = "") => { + if (dialog.open) dialog.close(String(value)); + }; + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (button?.matches("[data-open]")) { + show(button); + return; + } + if (button && dialog.contains(button) && enabled(button)) { + if (button.matches("[data-close],.dialog-close,.drawer-close")) close(button.dataset.close ?? "cancel"); + else if (button.dataset.action && root.emit("action", { action: button.dataset.action })) close(button.dataset.action); + } + if (root.constructor.componentId === "drawer" && event.target.closest("a[href]") && dialog.contains(event.target)) close("navigate"); + }); + on(dialog, "cancel", (event) => { + if (!root.emit("cancel", {})) event.preventDefault(); + }); + on(dialog, "close", () => { + if (opener?.isConnected) opener.focus(); + root.emit("close", { returnValue: dialog.returnValue }); + }); + return { + show, + close, + get open() { + return dialog.open; + }, + set open(value) { + value ? show() : close(); + }, + get returnValue() { + return dialog.returnValue; + }, + cleanup() { + if (dialog.open) dialog.close(); + } + }; +} +function tooltip(root, { on }) { + const trigger = root.querySelector(".tooltip-trigger"), popup = root.querySelector("[role=\"tooltip\"]"); + if (!trigger || !popup) return {}; + identify(root, popup, "tooltip"); + trigger.setAttribute("aria-describedby", popup.id); + let timer, hideTimer, dismissed = false, hovering = false; + const stop = () => { + clearTimeout(timer); + clearTimeout(hideTimer); + }; + const hide = () => { + stop(); + popup.hidden = true; + }; + const show = () => { + stop(); + if (!dismissed) { + popup.hidden = false; + place(trigger, popup); + } + }; + const hideSoon = () => { + clearTimeout(timer); + clearTimeout(hideTimer); + hideTimer = setTimeout(() => { + if (!hovering && root.ownerDocument.activeElement !== trigger) hide(); + }, 300); + }; + on(trigger, "pointerenter", (event) => { + if (event.pointerType !== "touch") { + hovering = true; + dismissed = false; + clearTimeout(hideTimer); + if (popup.hidden) timer = setTimeout(show, 300); + } + }); + on(root, "pointerleave", (event) => { + if (!root.contains(event.relatedTarget)) { + hovering = false; + dismissed = false; + if (root.ownerDocument.activeElement !== trigger) hideSoon(); + } + }); + on(popup, "pointerenter", () => { + hovering = true; + stop(); + }); + on(trigger, "focus", () => { + dismissed = false; + show(); + }); + on(trigger, "blur", () => { + if (!hovering) hide(); + }); + on(trigger, "click", () => { + dismissed = true; + hide(); + }); + on(trigger, "pointerdown", (event) => { + if (event.pointerType === "touch") { + dismissed = false; + timer = setTimeout(show, 500); + } + }); + on(trigger, "pointerup", stop); + on(trigger, "pointercancel", stop); + on(root.ownerDocument, "keydown", (event) => { + if (event.key === "Escape" && !popup.hidden) { + event.preventDefault(); + event.stopImmediatePropagation(); + dismissed = true; + hide(); + } + }, { capture: true }); + on(root.ownerDocument, "scroll", () => { + if (!popup.hidden) place(trigger, popup); + }, { capture: true }); + on(root.ownerDocument.defaultView, "resize", () => { + if (!popup.hidden) place(trigger, popup); + }); + hide(); + return { + show, + hide, + get open() { + return !popup.hidden; + }, + cleanup: hide + }; +} +function popover(root, { on }) { + const trigger = root.querySelector("[data-popover-trigger]"), panel = root.querySelector("[data-popover-panel]"); + if (!trigger || !panel) return {}; + identify(root, panel, "popover"); + trigger.setAttribute("aria-controls", panel.id); + const native = typeof panel.showPopover === "function"; + if (native) { + panel.setAttribute("popover", "auto"); + panel.hidden = false; + } else panel.hidden = true; + let open = false; + const sync = (value) => { + open = value; + trigger.setAttribute("aria-expanded", String(value)); + root.emit("toggle", { expanded: value }); + }; + const show = () => { + if (open || !enabled(trigger)) return; + native ? panel.showPopover() : panel.hidden = false; + sync(true); + place(trigger, panel); + }; + const hide = (focus = false) => { + if (!open) return; + native ? panel.hidePopover() : panel.hidden = true; + sync(false); + if (focus) trigger.focus(); + }; + on(trigger, "click", () => open ? hide() : show()); + on(panel, "beforetoggle", (event) => { + open = event.newState === "open"; + trigger.setAttribute("aria-expanded", String(open)); + }); + on(panel, "click", (event) => { + if (event.target.closest("[data-close]")) hide(true); + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!native && !root.contains(event.target)) hide(); + }); + on(root, "keydown", (event) => { + if (event.key === "Escape" && open) { + event.preventDefault(); + event.stopPropagation(); + hide(true); + } + }); + on(root.ownerDocument.defaultView, "resize", () => { + if (open) place(trigger, panel); + }); + trigger.setAttribute("aria-expanded", "false"); + return { + show, + hide, + get open() { + return open; + }, + set open(value) { + value ? show() : hide(); + }, + cleanup() { + hide(); + } + }; +} +function feedback(root, { on }) { + const dismiss = (item) => { + if (!item || !root.emit("dismiss", { id: item.id })) return; + const hadFocus = item.contains(root.ownerDocument.activeElement); + const focusable = all(root.ownerDocument, "button,a[href],input,select,textarea,[tabindex='0']").filter((node) => enabled(node) && !node.closest("[hidden]")); + const currentIndex = focusable.indexOf(root.ownerDocument.activeElement); + const next = focusable.slice(currentIndex + 1).find((node) => !item.contains(node)) ?? focusable.slice(0, currentIndex).reverse().find((node) => !item.contains(node)); + item.hidden = true; + if (hadFocus) next?.focus(); + }; + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button)) return; + if (button.matches(".toast-close,.alert-close,.chip-remove,[data-dismiss]")) dismiss(button.closest(".toast,.alert,.chip") ?? root); + else if (button.matches(".chip-filter")) { + button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + root.emit("action", { + action: button.textContent.trim(), + pressed: button.getAttribute("aria-pressed") === "true" + }); + } else if (button.matches("[data-retry]")) root.emit("retry", {}); + else root.emit("action", { action: button.dataset.action ?? button.textContent.trim() }); + }); + on(root, "keydown", (event) => { + if (event.key === "Escape") { + const toast = event.target.closest(".toast"); + if (toast) { + event.preventDefault(); + event.stopPropagation(); + dismiss(toast); + } + } + }); + return { dismiss(id) { + dismiss(id ? root.querySelector(`#${CSS.escape(id)}`) : root.querySelector(".toast,.alert") ?? root); + } }; +} +export { tooltip as i, modal as n, popover as r, feedback as t }; diff --git a/packages/ui/dist/copy/toast/runtime/chunks/overlays-BwgpF4jI.js b/packages/ui/dist/copy/toast/runtime/chunks/overlays-BwgpF4jI.js deleted file mode 100644 index 4b8de2e8b..000000000 --- a/packages/ui/dist/copy/toast/runtime/chunks/overlays-BwgpF4jI.js +++ /dev/null @@ -1,245 +0,0 @@ -import { d as place, i as all, o as enabled, s as identify } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/overlays.js -function modal(root, { on }) { - const dialog = root.querySelector("dialog"); - if (!dialog) return {}; - let opener = null; - const show = (trigger = root.ownerDocument.activeElement) => { - if (dialog.open || root.hasAttribute("disabled")) return; - opener = trigger; - dialog.showModal(); - (dialog.querySelector("[autofocus]") ?? dialog.querySelector("button:not(.dialog-button-destructive)"))?.focus(); - root.emit("open", {}); - }; - const close = (value = "") => { - if (dialog.open) dialog.close(String(value)); - }; - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (button?.matches("[data-open]")) { - show(button); - return; - } - if (button && dialog.contains(button) && enabled(button)) { - if (button.matches("[data-close],.dialog-close,.drawer-close")) close(button.dataset.close ?? "cancel"); - else if (button.dataset.action && root.emit("action", { action: button.dataset.action })) close(button.dataset.action); - } - if (root.constructor.componentId === "drawer" && event.target.closest("a[href]") && dialog.contains(event.target)) close("navigate"); - }); - on(dialog, "cancel", (event) => { - if (!root.emit("cancel", {})) event.preventDefault(); - }); - on(dialog, "close", () => { - if (opener?.isConnected) opener.focus(); - root.emit("close", { returnValue: dialog.returnValue }); - }); - return { - show, - close, - get open() { - return dialog.open; - }, - set open(value) { - value ? show() : close(); - }, - get returnValue() { - return dialog.returnValue; - }, - cleanup() { - if (dialog.open) dialog.close(); - } - }; -} -function tooltip(root, { on }) { - const trigger = root.querySelector(".tooltip-trigger"), popup = root.querySelector("[role=\"tooltip\"]"); - if (!trigger || !popup) return {}; - identify(root, popup, "tooltip"); - trigger.setAttribute("aria-describedby", popup.id); - let timer, hideTimer, dismissed = false, hovering = false; - const stop = () => { - clearTimeout(timer); - clearTimeout(hideTimer); - }; - const hide = () => { - stop(); - popup.hidden = true; - }; - const show = () => { - stop(); - if (!dismissed) { - popup.hidden = false; - place(trigger, popup); - } - }; - const hideSoon = () => { - clearTimeout(timer); - clearTimeout(hideTimer); - hideTimer = setTimeout(() => { - if (!hovering && root.ownerDocument.activeElement !== trigger) hide(); - }, 300); - }; - on(trigger, "pointerenter", (event) => { - if (event.pointerType !== "touch") { - hovering = true; - dismissed = false; - clearTimeout(hideTimer); - if (popup.hidden) timer = setTimeout(show, 300); - } - }); - on(root, "pointerleave", (event) => { - if (!root.contains(event.relatedTarget)) { - hovering = false; - dismissed = false; - if (root.ownerDocument.activeElement !== trigger) hideSoon(); - } - }); - on(popup, "pointerenter", () => { - hovering = true; - stop(); - }); - on(trigger, "focus", () => { - dismissed = false; - show(); - }); - on(trigger, "blur", () => { - if (!hovering) hide(); - }); - on(trigger, "click", () => { - dismissed = true; - hide(); - }); - on(trigger, "pointerdown", (event) => { - if (event.pointerType === "touch") { - dismissed = false; - timer = setTimeout(show, 500); - } - }); - on(trigger, "pointerup", stop); - on(trigger, "pointercancel", stop); - on(root.ownerDocument, "keydown", (event) => { - if (event.key === "Escape" && !popup.hidden) { - event.preventDefault(); - event.stopImmediatePropagation(); - dismissed = true; - hide(); - } - }, { capture: true }); - on(root.ownerDocument, "scroll", () => { - if (!popup.hidden) place(trigger, popup); - }, { capture: true }); - on(root.ownerDocument.defaultView, "resize", () => { - if (!popup.hidden) place(trigger, popup); - }); - hide(); - return { - show, - hide, - get open() { - return !popup.hidden; - }, - cleanup: hide - }; -} -function popover(root, { on }) { - const trigger = root.querySelector("[data-popover-trigger]"), panel = root.querySelector("[data-popover-panel]"); - if (!trigger || !panel) return {}; - identify(root, panel, "popover"); - trigger.setAttribute("aria-controls", panel.id); - const native = typeof panel.showPopover === "function"; - if (native) { - panel.setAttribute("popover", "auto"); - panel.hidden = false; - } else panel.hidden = true; - let open = false; - const sync = (value) => { - open = value; - trigger.setAttribute("aria-expanded", String(value)); - root.emit("toggle", { expanded: value }); - }; - const show = () => { - if (open || !enabled(trigger)) return; - native ? panel.showPopover() : panel.hidden = false; - sync(true); - place(trigger, panel); - }; - const hide = (focus = false) => { - if (!open) return; - native ? panel.hidePopover() : panel.hidden = true; - sync(false); - if (focus) trigger.focus(); - }; - on(trigger, "click", () => open ? hide() : show()); - on(panel, "beforetoggle", (event) => { - open = event.newState === "open"; - trigger.setAttribute("aria-expanded", String(open)); - }); - on(panel, "click", (event) => { - if (event.target.closest("[data-close]")) hide(true); - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!native && !root.contains(event.target)) hide(); - }); - on(root, "keydown", (event) => { - if (event.key === "Escape" && open) { - event.preventDefault(); - event.stopPropagation(); - hide(true); - } - }); - on(root.ownerDocument.defaultView, "resize", () => { - if (open) place(trigger, panel); - }); - trigger.setAttribute("aria-expanded", "false"); - return { - show, - hide, - get open() { - return open; - }, - set open(value) { - value ? show() : hide(); - }, - cleanup() { - hide(); - } - }; -} -function feedback(root, { on }) { - const dismiss = (item) => { - if (!item || !root.emit("dismiss", { id: item.id })) return; - const hadFocus = item.contains(root.ownerDocument.activeElement); - const focusable = all(root.ownerDocument, "button,a[href],input,select,textarea,[tabindex='0']").filter((node) => enabled(node) && !node.closest("[hidden]")); - const currentIndex = focusable.indexOf(root.ownerDocument.activeElement); - const next = focusable.slice(currentIndex + 1).find((node) => !item.contains(node)) ?? focusable.slice(0, currentIndex).reverse().find((node) => !item.contains(node)); - item.hidden = true; - if (hadFocus) next?.focus(); - }; - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button)) return; - if (button.matches(".toast-close,.alert-close,.chip-remove,[data-dismiss]")) dismiss(button.closest(".toast,.alert,.chip") ?? root); - else if (button.matches(".chip-filter")) { - button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - root.emit("action", { - action: button.textContent.trim(), - pressed: button.getAttribute("aria-pressed") === "true" - }); - } else if (button.matches("[data-retry]")) root.emit("retry", {}); - else root.emit("action", { action: button.dataset.action ?? button.textContent.trim() }); - }); - on(root, "keydown", (event) => { - if (event.key === "Escape") { - const toast = event.target.closest(".toast"); - if (toast) { - event.preventDefault(); - event.stopPropagation(); - dismiss(toast); - } - } - }); - return { dismiss(id) { - dismiss(id ? root.querySelector(`#${CSS.escape(id)}`) : root.querySelector(".toast,.alert") ?? root); - } }; -} -//#endregion -export { tooltip as i, modal as n, popover as r, feedback as t }; diff --git a/packages/ui/dist/copy/toast/runtime/components/toast.js b/packages/ui/dist/copy/toast/runtime/components/toast.js index 46f24a535..905544ae0 100644 --- a/packages/ui/dist/copy/toast/runtime/components/toast.js +++ b/packages/ui/dist/copy/toast/runtime/components/toast.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { t as feedback } from "../chunks/overlays-BwgpF4jI.js"; -//#region .cache/ui-build/entries/components/toast.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { t as feedback } from "../chunks/overlays-BW66WXLm.js"; +// .cache/ui-build/entries/components/toast.js var J3w1Toast = class extends J3w1Element { static componentId = "toast"; static version = "4.0.0"; - static implementationId = "sha256-j9WKre9usZOe/7NyvL2T/LvVxN+aLguS4DKMT0466EQ="; + static implementationId = "sha256-ywJbcX+iwfyImi8hYwyUwIemYNa3TJIvKqVcolt3uzE="; static connect = feedback; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -13,5 +13,4 @@ var J3w1Toast = class extends J3w1Element { return this._api.dismiss(...args); } }; -//#endregion export { J3w1Toast }; diff --git a/packages/ui/dist/copy/toast/runtime/register/toast.js b/packages/ui/dist/copy/toast/runtime/register/toast.js index 55941b8ec..b0003944d 100644 --- a/packages/ui/dist/copy/toast/runtime/register/toast.js +++ b/packages/ui/dist/copy/toast/runtime/register/toast.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Toast } from "../components/toast.js"; -//#region .cache/ui-build/entries/register/toast.js +// .cache/ui-build/entries/register/toast.js var element = registerElement("j3w1-toast", J3w1Toast); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/toolbar/manifest.json b/packages/ui/dist/copy/toolbar/manifest.json index 798bbc3ad..b987a31e3 100644 --- a/packages/ui/dist/copy/toolbar/manifest.json +++ b/packages/ui/dist/copy/toolbar/manifest.json @@ -5,21 +5,21 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/toolbar.md", "dependencies": [ "register/toolbar.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/toolbar.js", - "chunks/navigation-BfNzDYZB.js", + "chunks/navigation-CknoksQ5.js", "register/menu.js", "components/menu.js" ], "files": { - "runtime/register/toolbar.js": "sha256-0i+oWvmcjNoFTB9ChlJSM3r3Ig4bYjlkdy/lkmNBlmA=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/toolbar.js": "sha256-kGWjidatkl+BJM+S2e/e9pYaok6mLuLLl520Nn8h86E=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", - "runtime/register/menu.js": "sha256-6CvU7Rei9lC+olXvluxdbCPqh46GrPSvB2MGiudiMTk=", - "runtime/components/menu.js": "sha256-As/aVex/jKXrmY4x/rG0tVMVUij8ZLPXK0kKS4ZBpSQ=", + "runtime/register/toolbar.js": "sha256-Gf7THPkn4x1hVyTl/jXRoGd2Oa5RL8dK8uqHQV+pqxQ=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/toolbar.js": "sha256-/Uxx9EzorKPSd2FGVPpk5AnASvRBGVfcGONUJd8x9LE=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", + "runtime/register/menu.js": "sha256-du/4u8ykElicgf7iZHv6rD5yz/4njOxzodjcqCcr0d8=", + "runtime/components/menu.js": "sha256-qz11rQvGk4omYnKEFWVz4SXD3R4xn/UhG0nt4oqFtJw=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-zD6jRNAjuf7XM9+QaxwzEY+F2cFUrQbgUKNLTCc7Q/Y=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/toolbar/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/toolbar/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/toolbar/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/toolbar/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/toolbar/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/toolbar/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/toolbar/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/toolbar/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/toolbar/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/toolbar/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/toolbar/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/toolbar/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/toolbar/runtime/chunks/navigation-BfNzDYZB.js b/packages/ui/dist/copy/toolbar/runtime/chunks/navigation-BfNzDYZB.js deleted file mode 100644 index db2779553..000000000 --- a/packages/ui/dist/copy/toolbar/runtime/chunks/navigation-BfNzDYZB.js +++ /dev/null @@ -1,377 +0,0 @@ -import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/navigation.js -function tabs(root, { on }, listOverride) { - const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); - if (!list) return {}; - const items = () => all(list, "[role=\"tab\"]").filter(enabled); - const select = (id, focus = false) => { - const tab = items().find((item) => item.id === id); - if (!tab) throw new RangeError(`Unknown enabled tab: ${id}`); - all(list, "[role=\"tab\"]").forEach((item) => { - item.setAttribute("aria-selected", String(item === tab)); - item.tabIndex = item === tab ? 0 : -1; - }); - all(root, "[role=\"tabpanel\"]").filter((panel) => all(list, "[role=\"tab\"]").some((tab) => tab.getAttribute("aria-controls") === panel.id)).forEach((panel) => { - panel.hidden = panel.id !== tab.getAttribute("aria-controls"); - if (!panel.hidden && !panel.querySelector("a[href],button,input,select,textarea,[tabindex='0']")) panel.tabIndex = 0; - }); - if (focus) tab.focus(); - return tab; - }; - const activate = (tab) => { - select(tab.id); - root.emit("select", { - id: tab.id, - panelId: tab.getAttribute("aria-controls") - }); - }; - on(list, "click", (event) => { - const tab = event.target.closest("[role=\"tab\"]"); - if (tab && enabled(tab)) activate(tab); - }); - on(list, "keydown", (event) => { - const current = event.target.closest("[role=\"tab\"]"), options = items(); - if (!current) return; - const vertical = list.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(list).direction === "rtl"; - const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", previous = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; - let index = options.indexOf(current); - if (event.key === next) index++; - else if (event.key === previous) index--; - else if (event.key === "Home") index = 0; - else if (event.key === "End") index = options.length - 1; - else if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - activate(current); - return; - } else return; - event.preventDefault(); - const tab = rove(options, index); - if (root.getAttribute("activation") !== "manual") activate(tab); - }); - const initial = items().find((item) => item.getAttribute("aria-selected") === "true") ?? items()[0]; - if (initial) select(initial.id); - return { - select, - get selectedId() { - return list.querySelector("[aria-selected=\"true\"]")?.id ?? ""; - }, - set selectedId(id) { - select(id); - } - }; -} -function toolbar(root, { on }) { - const bar = root.querySelector("[role=\"toolbar\"]"); - if (!bar) return {}; - const controls = () => all(bar, "button,a[href],input,select").filter((node) => enabled(node) && visible(node) && !node.closest("[role=\"menu\"]")); - const initial = controls(); - rove(initial, Math.max(0, initial.findIndex((node) => node.tabIndex === 0)), false); - on(bar, "focusin", (event) => { - if (controls().includes(event.target)) rove(controls(), controls().indexOf(event.target), false); - }); - on(bar, "keydown", (event) => { - if (event.target.matches("input,select,textarea") || event.target.closest("[role=\"menu\"]")) return; - const items = controls(), index = items.indexOf(event.target); - const vertical = bar.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(bar).direction === "rtl"; - const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", prev = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; - if (![ - next, - prev, - "Home", - "End" - ].includes(event.key)) return; - event.preventDefault(); - rove(items, keyIndex({ - key: event.key, - index, - length: items.length, - next, - previous: prev - })); - }); - on(bar, "click", (event) => { - const button = event.target.closest("button[aria-pressed]"); - if (button && enabled(button)) { - button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - root.emit("action", { - action: button.dataset.action ?? button.textContent.trim(), - pressed: button.getAttribute("aria-pressed") === "true" - }); - } - }); - return {}; -} -function disclosure(root, { on }) { - on(root, "click", (event) => { - const button = event.target.closest("button[aria-controls][aria-expanded]"); - if (!button || !enabled(button)) return; - const target = root.querySelector(`#${CSS.escape(button.getAttribute("aria-controls"))}`); - if (!target) return; - const expanded = button.getAttribute("aria-expanded") !== "true"; - button.setAttribute("aria-expanded", String(expanded)); - target.hidden = !expanded; - root.emit("toggle", { - id: target.id, - expanded - }); - }); - const details = root.querySelector("details"); - on(details, "toggle", () => root.emit("toggle", { - id: details.id, - expanded: details.open - })); - return { - get open() { - return details?.open ?? false; - }, - set open(value) { - if (details) details.open = Boolean(value); - } - }; -} -function combobox(root, { on, signal }) { - const input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"); - if (!input || !list) return {}; - identify(root, list, "options"); - input.setAttribute("aria-controls", list.id); - let active = null, notifying = false; - const notify = () => { - notifying = true; - try { - nativeInput(input); - nativeInput(input, "change"); - } finally { - notifying = false; - } - }; - const options = () => all(list, "[role=\"option\"]").filter((node) => enabled(node) && !node.hidden && !node.closest("[role=\"group\"][hidden]")); - all(list, "[role=\"option\"]").forEach((option, index) => identify(root, option, `option-${index}`)); - const setActive = (option) => { - active = option; - all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); - if (option) { - input.setAttribute("aria-activedescendant", option.id); - option.scrollIntoView({ block: "nearest" }); - } else input.removeAttribute("aria-activedescendant"); - }; - const hide = () => { - list.hidden = true; - input.setAttribute("aria-expanded", "false"); - setActive(null); - }; - const filter = (query = input.value) => { - for (const option of all(list, "[role=\"option\"]")) if (enabled(option)) option.hidden = !option.textContent.toLocaleLowerCase().includes(query.toLocaleLowerCase()); - all(list, "[role=\"group\"]").forEach((group) => { - group.hidden = !all(group, "[role=\"option\"]").some((node) => enabled(node) && !node.hidden); - }); - const empty = root.querySelector(".combobox-empty"); - if (empty) { - empty.hidden = options().length !== 0; - empty.classList.toggle("combobox-empty-shown", !empty.hidden); - } - if (!options().includes(active)) setActive(null); - }; - const show = (allOptions = false) => { - if (!enabled(input) || input.readOnly) return; - filter(allOptions ? "" : input.value); - list.hidden = false; - input.setAttribute("aria-expanded", "true"); - place(input, list); - }; - const choose = (option) => { - if (!option || !enabled(option)) return; - input.value = option.dataset.value ?? option.textContent.trim(); - hide(); - notify(); - input.focus(); - }; - on(input, "input", () => { - if (!notifying) { - show(); - announce(root, `${options().length} options available.`); - } - }); - on(input, "keydown", (event) => { - if (event.key === "Tab") { - hide(); - return; - } - if (event.key === "Escape") { - if (!list.hidden) { - hide(); - event.stopPropagation(); - } else if (input.value) { - input.value = ""; - notify(); - event.stopPropagation(); - } - event.preventDefault(); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - hide(); - return; - } - if (["ArrowDown", "ArrowUp"].includes(event.key)) { - event.preventDefault(); - if (list.hidden) show(true); - if (event.altKey) return; - const items = options(), index = active ? items.indexOf(active) : event.key === "ArrowDown" ? -1 : 0; - if (items.length) setActive(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); - } else if (event.key === "Enter" && !list.hidden && active) { - event.preventDefault(); - choose(active); - } - }); - on(list, "pointerdown", (event) => { - if (event.target.closest("[role=\"option\"]")) event.preventDefault(); - }); - on(list, "click", (event) => choose(event.target.closest("[role=\"option\"]"))); - on(root.querySelector(".combobox-toggle"), "click", () => { - list.hidden ? show(true) : hide(); - input.focus(); - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!root.contains(event.target)) hide(); - }); - on(root, "focusout", () => queueMicrotask(() => { - if (!signal.aborted && !root.contains(root.ownerDocument.activeElement)) hide(); - })); - on(root.ownerDocument.defaultView, "resize", () => { - if (!list.hidden) place(input, list); - }); - on(root.ownerDocument, "scroll", (event) => { - if (!list.hidden && !list.contains(event.target)) place(input, list); - }, { capture: true }); - hide(); - return { - show, - hide, - get open() { - return !list.hidden; - }, - set open(value) { - value ? show() : hide(); - }, - get value() { - return input.value; - }, - set value(value) { - input.value = String(value ?? ""); - if (!list.hidden) filter(); - }, - cleanup: hide - }; -} -function menu(root, { on }) { - const trigger = root.querySelector("button[aria-haspopup=\"menu\"]"), main = root.querySelector("[role=\"menu\"]"); - if (!trigger || !main) return {}; - identify(root, main, "menu"); - trigger.setAttribute("aria-controls", main.id); - const lists = all(root, "[role=\"menu\"]"); - const items = (list) => all(list, "[role^=\"menuitem\"]").filter((item) => item.closest("[role=\"menu\"]") === list); - const controller = (list) => all(root, "[aria-controls]").find((node) => node.getAttribute("aria-controls") === list.id); - const closeList = (list) => { - list.hidden = true; - controller(list)?.setAttribute("aria-expanded", "false"); - }; - const hide = (focus = true) => { - lists.forEach(closeList); - if (focus) trigger.focus(); - }; - const showList = (list, button, last = false) => { - list.hidden = false; - button.setAttribute("aria-expanded", "true"); - place(button, list); - rove(items(list), last ? items(list).length - 1 : 0); - }; - const show = () => { - if (enabled(trigger)) showList(main, trigger); - }; - const submenu = (button) => button.hasAttribute("aria-haspopup") ? lists.find((list) => list.id === button.getAttribute("aria-controls")) : null; - const activate = (item) => { - if (!enabled(item)) return; - const child = submenu(item); - if (child) { - showList(child, item); - return; - } - if (item.getAttribute("role") === "menuitemcheckbox") item.setAttribute("aria-checked", String(item.getAttribute("aria-checked") !== "true")); - else if (item.getAttribute("role") === "menuitemradio") items(item.closest("[role=\"menu\"]")).filter((node) => node.getAttribute("role") === "menuitemradio").forEach((node) => node.setAttribute("aria-checked", String(node === item))); - else hide(); - root.emit("action", { - action: item.dataset.action ?? item.textContent.trim(), - checked: item.getAttribute("aria-checked") === "true" - }); - }; - on(trigger, "click", () => main.hidden ? show() : hide()); - on(trigger, "keydown", (event) => { - if (["ArrowDown", "ArrowUp"].includes(event.key) && enabled(trigger)) { - event.preventDefault(); - showList(main, trigger, event.key === "ArrowUp"); - } - }); - on(root, "click", (event) => { - const item = event.target.closest("[role^=\"menuitem\"]"); - if (item) activate(item); - }); - on(root, "keydown", (event) => { - const item = event.target.closest("[role^=\"menuitem\"]"); - if (!item) return; - const list = item.closest("[role=\"menu\"]"), options = items(list), index = options.indexOf(item), rtl = getComputedStyle(list).direction === "rtl"; - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - rove(options, keyIndex({ - key: event.key, - index, - length: options.length - })); - } else if (event.key === "Escape" || event.key === (rtl ? "ArrowRight" : "ArrowLeft") && list !== main) { - event.preventDefault(); - event.stopPropagation(); - if (list !== main) { - closeList(list); - controller(list)?.focus(); - } else hide(); - } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight") && submenu(item)) { - event.preventDefault(); - showList(submenu(item), item); - } else if (event.key === "Tab") hide(); - else if (event.key.length === 1 && /\S/.test(event.key)) { - const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(".menu-label") ?? node).textContent.trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); - if (found) { - event.preventDefault(); - rove(options, options.indexOf(found)); - } - } - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!root.contains(event.target)) hide(false); - }); - on(root.ownerDocument, "focusin", (event) => { - if (!root.contains(event.target)) hide(false); - }); - on(root.ownerDocument.defaultView, "resize", () => lists.filter((list) => !list.hidden).forEach((list) => place(controller(list), list))); - hide(false); - return { - show, - hide, - get open() { - return !main.hidden; - }, - set open(value) { - value ? show() : hide(false); - }, - cleanup() { - hide(false); - } - }; -} -//#endregion -export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/toolbar/runtime/chunks/navigation-CknoksQ5.js b/packages/ui/dist/copy/toolbar/runtime/chunks/navigation-CknoksQ5.js new file mode 100644 index 000000000..dfd1883e6 --- /dev/null +++ b/packages/ui/dist/copy/toolbar/runtime/chunks/navigation-CknoksQ5.js @@ -0,0 +1,376 @@ +import { a as announce, c as keyIndex, d as place, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/navigation.js +function tabs(root, { on }, listOverride) { + const list = listOverride ?? root.querySelector("[role=\"tablist\"]"); + if (!list) return {}; + const items = () => all(list, "[role=\"tab\"]").filter(enabled); + const select = (id, focus = false) => { + const tab = items().find((item) => item.id === id); + if (!tab) throw new RangeError(`Unknown enabled tab: ${id}`); + all(list, "[role=\"tab\"]").forEach((item) => { + item.setAttribute("aria-selected", String(item === tab)); + item.tabIndex = item === tab ? 0 : -1; + }); + all(root, "[role=\"tabpanel\"]").filter((panel) => all(list, "[role=\"tab\"]").some((tab) => tab.getAttribute("aria-controls") === panel.id)).forEach((panel) => { + panel.hidden = panel.id !== tab.getAttribute("aria-controls"); + if (!panel.hidden && !panel.querySelector("a[href],button,input,select,textarea,[tabindex='0']")) panel.tabIndex = 0; + }); + if (focus) tab.focus(); + return tab; + }; + const activate = (tab) => { + select(tab.id); + root.emit("select", { + id: tab.id, + panelId: tab.getAttribute("aria-controls") + }); + }; + on(list, "click", (event) => { + const tab = event.target.closest("[role=\"tab\"]"); + if (tab && enabled(tab)) activate(tab); + }); + on(list, "keydown", (event) => { + const current = event.target.closest("[role=\"tab\"]"), options = items(); + if (!current) return; + const vertical = list.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(list).direction === "rtl"; + const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", previous = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; + let index = options.indexOf(current); + if (event.key === next) index++; + else if (event.key === previous) index--; + else if (event.key === "Home") index = 0; + else if (event.key === "End") index = options.length - 1; + else if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + activate(current); + return; + } else return; + event.preventDefault(); + const tab = rove(options, index); + if (root.getAttribute("activation") !== "manual") activate(tab); + }); + const initial = items().find((item) => item.getAttribute("aria-selected") === "true") ?? items()[0]; + if (initial) select(initial.id); + return { + select, + get selectedId() { + return list.querySelector("[aria-selected=\"true\"]")?.id ?? ""; + }, + set selectedId(id) { + select(id); + } + }; +} +function toolbar(root, { on }) { + const bar = root.querySelector("[role=\"toolbar\"]"); + if (!bar) return {}; + const controls = () => all(bar, "button,a[href],input,select").filter((node) => enabled(node) && visible(node) && !node.closest("[role=\"menu\"]")); + const initial = controls(); + rove(initial, Math.max(0, initial.findIndex((node) => node.tabIndex === 0)), false); + on(bar, "focusin", (event) => { + if (controls().includes(event.target)) rove(controls(), controls().indexOf(event.target), false); + }); + on(bar, "keydown", (event) => { + if (event.target.matches("input,select,textarea") || event.target.closest("[role=\"menu\"]")) return; + const items = controls(), index = items.indexOf(event.target); + const vertical = bar.getAttribute("aria-orientation") === "vertical", rtl = getComputedStyle(bar).direction === "rtl"; + const next = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight", prev = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft"; + if (![ + next, + prev, + "Home", + "End" + ].includes(event.key)) return; + event.preventDefault(); + rove(items, keyIndex({ + key: event.key, + index, + length: items.length, + next, + previous: prev + })); + }); + on(bar, "click", (event) => { + const button = event.target.closest("button[aria-pressed]"); + if (button && enabled(button)) { + button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + root.emit("action", { + action: button.dataset.action ?? button.textContent.trim(), + pressed: button.getAttribute("aria-pressed") === "true" + }); + } + }); + return {}; +} +function disclosure(root, { on }) { + on(root, "click", (event) => { + const button = event.target.closest("button[aria-controls][aria-expanded]"); + if (!button || !enabled(button)) return; + const target = root.querySelector(`#${CSS.escape(button.getAttribute("aria-controls"))}`); + if (!target) return; + const expanded = button.getAttribute("aria-expanded") !== "true"; + button.setAttribute("aria-expanded", String(expanded)); + target.hidden = !expanded; + root.emit("toggle", { + id: target.id, + expanded + }); + }); + const details = root.querySelector("details"); + on(details, "toggle", () => root.emit("toggle", { + id: details.id, + expanded: details.open + })); + return { + get open() { + return details?.open ?? false; + }, + set open(value) { + if (details) details.open = Boolean(value); + } + }; +} +function combobox(root, { on, signal }) { + const input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"); + if (!input || !list) return {}; + identify(root, list, "options"); + input.setAttribute("aria-controls", list.id); + let active = null, notifying = false; + const notify = () => { + notifying = true; + try { + nativeInput(input); + nativeInput(input, "change"); + } finally { + notifying = false; + } + }; + const options = () => all(list, "[role=\"option\"]").filter((node) => enabled(node) && !node.hidden && !node.closest("[role=\"group\"][hidden]")); + all(list, "[role=\"option\"]").forEach((option, index) => identify(root, option, `option-${index}`)); + const setActive = (option) => { + active = option; + all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); + if (option) { + input.setAttribute("aria-activedescendant", option.id); + option.scrollIntoView({ block: "nearest" }); + } else input.removeAttribute("aria-activedescendant"); + }; + const hide = () => { + list.hidden = true; + input.setAttribute("aria-expanded", "false"); + setActive(null); + }; + const filter = (query = input.value) => { + for (const option of all(list, "[role=\"option\"]")) if (enabled(option)) option.hidden = !option.textContent.toLocaleLowerCase().includes(query.toLocaleLowerCase()); + all(list, "[role=\"group\"]").forEach((group) => { + group.hidden = !all(group, "[role=\"option\"]").some((node) => enabled(node) && !node.hidden); + }); + const empty = root.querySelector(".combobox-empty"); + if (empty) { + empty.hidden = options().length !== 0; + empty.classList.toggle("combobox-empty-shown", !empty.hidden); + } + if (!options().includes(active)) setActive(null); + }; + const show = (allOptions = false) => { + if (!enabled(input) || input.readOnly) return; + filter(allOptions ? "" : input.value); + list.hidden = false; + input.setAttribute("aria-expanded", "true"); + place(input, list); + }; + const choose = (option) => { + if (!option || !enabled(option)) return; + input.value = option.dataset.value ?? option.textContent.trim(); + hide(); + notify(); + input.focus(); + }; + on(input, "input", () => { + if (!notifying) { + show(); + announce(root, `${options().length} options available.`); + } + }); + on(input, "keydown", (event) => { + if (event.key === "Tab") { + hide(); + return; + } + if (event.key === "Escape") { + if (!list.hidden) { + hide(); + event.stopPropagation(); + } else if (input.value) { + input.value = ""; + notify(); + event.stopPropagation(); + } + event.preventDefault(); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + hide(); + return; + } + if (["ArrowDown", "ArrowUp"].includes(event.key)) { + event.preventDefault(); + if (list.hidden) show(true); + if (event.altKey) return; + const items = options(), index = active ? items.indexOf(active) : event.key === "ArrowDown" ? -1 : 0; + if (items.length) setActive(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); + } else if (event.key === "Enter" && !list.hidden && active) { + event.preventDefault(); + choose(active); + } + }); + on(list, "pointerdown", (event) => { + if (event.target.closest("[role=\"option\"]")) event.preventDefault(); + }); + on(list, "click", (event) => choose(event.target.closest("[role=\"option\"]"))); + on(root.querySelector(".combobox-toggle"), "click", () => { + list.hidden ? show(true) : hide(); + input.focus(); + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!root.contains(event.target)) hide(); + }); + on(root, "focusout", () => queueMicrotask(() => { + if (!signal.aborted && !root.contains(root.ownerDocument.activeElement)) hide(); + })); + on(root.ownerDocument.defaultView, "resize", () => { + if (!list.hidden) place(input, list); + }); + on(root.ownerDocument, "scroll", (event) => { + if (!list.hidden && !list.contains(event.target)) place(input, list); + }, { capture: true }); + hide(); + return { + show, + hide, + get open() { + return !list.hidden; + }, + set open(value) { + value ? show() : hide(); + }, + get value() { + return input.value; + }, + set value(value) { + input.value = String(value ?? ""); + if (!list.hidden) filter(); + }, + cleanup: hide + }; +} +function menu(root, { on }) { + const trigger = root.querySelector("button[aria-haspopup=\"menu\"]"), main = root.querySelector("[role=\"menu\"]"); + if (!trigger || !main) return {}; + identify(root, main, "menu"); + trigger.setAttribute("aria-controls", main.id); + const lists = all(root, "[role=\"menu\"]"); + const items = (list) => all(list, "[role^=\"menuitem\"]").filter((item) => item.closest("[role=\"menu\"]") === list); + const controller = (list) => all(root, "[aria-controls]").find((node) => node.getAttribute("aria-controls") === list.id); + const closeList = (list) => { + list.hidden = true; + controller(list)?.setAttribute("aria-expanded", "false"); + }; + const hide = (focus = true) => { + lists.forEach(closeList); + if (focus) trigger.focus(); + }; + const showList = (list, button, last = false) => { + list.hidden = false; + button.setAttribute("aria-expanded", "true"); + place(button, list); + rove(items(list), last ? items(list).length - 1 : 0); + }; + const show = () => { + if (enabled(trigger)) showList(main, trigger); + }; + const submenu = (button) => button.hasAttribute("aria-haspopup") ? lists.find((list) => list.id === button.getAttribute("aria-controls")) : null; + const activate = (item) => { + if (!enabled(item)) return; + const child = submenu(item); + if (child) { + showList(child, item); + return; + } + if (item.getAttribute("role") === "menuitemcheckbox") item.setAttribute("aria-checked", String(item.getAttribute("aria-checked") !== "true")); + else if (item.getAttribute("role") === "menuitemradio") items(item.closest("[role=\"menu\"]")).filter((node) => node.getAttribute("role") === "menuitemradio").forEach((node) => node.setAttribute("aria-checked", String(node === item))); + else hide(); + root.emit("action", { + action: item.dataset.action ?? item.textContent.trim(), + checked: item.getAttribute("aria-checked") === "true" + }); + }; + on(trigger, "click", () => main.hidden ? show() : hide()); + on(trigger, "keydown", (event) => { + if (["ArrowDown", "ArrowUp"].includes(event.key) && enabled(trigger)) { + event.preventDefault(); + showList(main, trigger, event.key === "ArrowUp"); + } + }); + on(root, "click", (event) => { + const item = event.target.closest("[role^=\"menuitem\"]"); + if (item) activate(item); + }); + on(root, "keydown", (event) => { + const item = event.target.closest("[role^=\"menuitem\"]"); + if (!item) return; + const list = item.closest("[role=\"menu\"]"), options = items(list), index = options.indexOf(item), rtl = getComputedStyle(list).direction === "rtl"; + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + rove(options, keyIndex({ + key: event.key, + index, + length: options.length + })); + } else if (event.key === "Escape" || event.key === (rtl ? "ArrowRight" : "ArrowLeft") && list !== main) { + event.preventDefault(); + event.stopPropagation(); + if (list !== main) { + closeList(list); + controller(list)?.focus(); + } else hide(); + } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight") && submenu(item)) { + event.preventDefault(); + showList(submenu(item), item); + } else if (event.key === "Tab") hide(); + else if (event.key.length === 1 && /\S/.test(event.key)) { + const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(".menu-label") ?? node).textContent.trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); + if (found) { + event.preventDefault(); + rove(options, options.indexOf(found)); + } + } + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!root.contains(event.target)) hide(false); + }); + on(root.ownerDocument, "focusin", (event) => { + if (!root.contains(event.target)) hide(false); + }); + on(root.ownerDocument.defaultView, "resize", () => lists.filter((list) => !list.hidden).forEach((list) => place(controller(list), list))); + hide(false); + return { + show, + hide, + get open() { + return !main.hidden; + }, + set open(value) { + value ? show() : hide(false); + }, + cleanup() { + hide(false); + } + }; +} +export { toolbar as a, tabs as i, disclosure as n, menu as r, combobox as t }; diff --git a/packages/ui/dist/copy/toolbar/runtime/components/menu.js b/packages/ui/dist/copy/toolbar/runtime/components/menu.js index b35ceb43e..b7031703c 100644 --- a/packages/ui/dist/copy/toolbar/runtime/components/menu.js +++ b/packages/ui/dist/copy/toolbar/runtime/components/menu.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { r as menu } from "../chunks/navigation-BfNzDYZB.js"; -//#region .cache/ui-build/entries/components/menu.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { r as menu } from "../chunks/navigation-CknoksQ5.js"; +// .cache/ui-build/entries/components/menu.js var J3w1Menu = class extends J3w1Element { static componentId = "menu"; static version = "4.0.0"; - static implementationId = "sha256-oS0Ubl9rLRKcmk22aO7KDARBpUoA/Y7sR2AvyqabH+U="; + static implementationId = "sha256-eK7xkdMDWtplCwL1L9Yt83xHvFQIuO3z1yoixK4RXOo="; static connect = menu; static upgradeProperties = [ "disabled", @@ -32,5 +32,4 @@ var J3w1Menu = class extends J3w1Element { }); } }; -//#endregion export { J3w1Menu }; diff --git a/packages/ui/dist/copy/toolbar/runtime/components/toolbar.js b/packages/ui/dist/copy/toolbar/runtime/components/toolbar.js index 195494e1d..ab307309b 100644 --- a/packages/ui/dist/copy/toolbar/runtime/components/toolbar.js +++ b/packages/ui/dist/copy/toolbar/runtime/components/toolbar.js @@ -1,13 +1,12 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { a as toolbar } from "../chunks/navigation-BfNzDYZB.js"; -//#region .cache/ui-build/entries/components/toolbar.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { a as toolbar } from "../chunks/navigation-CknoksQ5.js"; +// .cache/ui-build/entries/components/toolbar.js var J3w1Toolbar = class extends J3w1Element { static componentId = "toolbar"; static version = "4.0.0"; - static implementationId = "sha256-VCE2y9mKILLuKe6e6CYb+KzHmhM/oKWGD3XWHaHGRw0="; + static implementationId = "sha256-MH79RqtTV8lNFKQ+8OCjx7laob8pZbNEXeokabRaYPg="; static connect = toolbar; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; }; -//#endregion export { J3w1Toolbar }; diff --git a/packages/ui/dist/copy/toolbar/runtime/register/menu.js b/packages/ui/dist/copy/toolbar/runtime/register/menu.js index 655b77a5a..e99b1d3df 100644 --- a/packages/ui/dist/copy/toolbar/runtime/register/menu.js +++ b/packages/ui/dist/copy/toolbar/runtime/register/menu.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Menu } from "../components/menu.js"; -//#region .cache/ui-build/entries/register/menu.js +// .cache/ui-build/entries/register/menu.js var element = registerElement("j3w1-menu", J3w1Menu); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/toolbar/runtime/register/toolbar.js b/packages/ui/dist/copy/toolbar/runtime/register/toolbar.js index 0de0d853e..492e4699c 100644 --- a/packages/ui/dist/copy/toolbar/runtime/register/toolbar.js +++ b/packages/ui/dist/copy/toolbar/runtime/register/toolbar.js @@ -1,7 +1,6 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Toolbar } from "../components/toolbar.js"; import "./menu.js"; -//#region .cache/ui-build/entries/register/toolbar.js +// .cache/ui-build/entries/register/toolbar.js var element = registerElement("j3w1-toolbar", J3w1Toolbar); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/tooltip/manifest.json b/packages/ui/dist/copy/tooltip/manifest.json index f7918670c..5600d9f30 100644 --- a/packages/ui/dist/copy/tooltip/manifest.json +++ b/packages/ui/dist/copy/tooltip/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/tooltip.md", "dependencies": [ "register/tooltip.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/tooltip.js", - "chunks/overlays-BwgpF4jI.js" + "chunks/overlays-BW66WXLm.js" ], "files": { - "runtime/register/tooltip.js": "sha256-G4uAYJmQJk4eTEhF1uHV44mtO+Vefw1Onc1nq3+iWlU=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/tooltip.js": "sha256-2j1hr66OBZli855FnMDI/StSj237p3llagSJpYZh1KU=", - "runtime/chunks/overlays-BwgpF4jI.js": "sha256-NAd99OT4kDsFp8IHscKRus2jY6XRsq+GMzplWbJsY4U=", + "runtime/register/tooltip.js": "sha256-F7E8JHr/JV4iZeeVJnARr64yUr2l01418fBM2UvligM=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/tooltip.js": "sha256-/JSDKAWa/JXNmAoOtDMptCVY8Pu5nChQ/4UK26P8KuU=", + "runtime/chunks/overlays-BW66WXLm.js": "sha256-Z9etmUpuDuykKbJkriLMz8iiYnOP9uMUAshKwoHc1I8=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-qYB8NrU6j0LSeluhANQt7hX4GwZJkfsCr7sElkRObAs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/tooltip/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/tooltip/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/tooltip/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/tooltip/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/tooltip/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/tooltip/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/tooltip/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/tooltip/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/tooltip/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/tooltip/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/tooltip/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/tooltip/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/tooltip/runtime/chunks/overlays-BW66WXLm.js b/packages/ui/dist/copy/tooltip/runtime/chunks/overlays-BW66WXLm.js new file mode 100644 index 000000000..d05c73b46 --- /dev/null +++ b/packages/ui/dist/copy/tooltip/runtime/chunks/overlays-BW66WXLm.js @@ -0,0 +1,244 @@ +import { d as place, i as all, o as enabled, s as identify } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/overlays.js +function modal(root, { on }) { + const dialog = root.querySelector("dialog"); + if (!dialog) return {}; + let opener = null; + const show = (trigger = root.ownerDocument.activeElement) => { + if (dialog.open || root.hasAttribute("disabled")) return; + opener = trigger; + dialog.showModal(); + (dialog.querySelector("[autofocus]") ?? dialog.querySelector("button:not(.dialog-button-destructive)"))?.focus(); + root.emit("open", {}); + }; + const close = (value = "") => { + if (dialog.open) dialog.close(String(value)); + }; + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (button?.matches("[data-open]")) { + show(button); + return; + } + if (button && dialog.contains(button) && enabled(button)) { + if (button.matches("[data-close],.dialog-close,.drawer-close")) close(button.dataset.close ?? "cancel"); + else if (button.dataset.action && root.emit("action", { action: button.dataset.action })) close(button.dataset.action); + } + if (root.constructor.componentId === "drawer" && event.target.closest("a[href]") && dialog.contains(event.target)) close("navigate"); + }); + on(dialog, "cancel", (event) => { + if (!root.emit("cancel", {})) event.preventDefault(); + }); + on(dialog, "close", () => { + if (opener?.isConnected) opener.focus(); + root.emit("close", { returnValue: dialog.returnValue }); + }); + return { + show, + close, + get open() { + return dialog.open; + }, + set open(value) { + value ? show() : close(); + }, + get returnValue() { + return dialog.returnValue; + }, + cleanup() { + if (dialog.open) dialog.close(); + } + }; +} +function tooltip(root, { on }) { + const trigger = root.querySelector(".tooltip-trigger"), popup = root.querySelector("[role=\"tooltip\"]"); + if (!trigger || !popup) return {}; + identify(root, popup, "tooltip"); + trigger.setAttribute("aria-describedby", popup.id); + let timer, hideTimer, dismissed = false, hovering = false; + const stop = () => { + clearTimeout(timer); + clearTimeout(hideTimer); + }; + const hide = () => { + stop(); + popup.hidden = true; + }; + const show = () => { + stop(); + if (!dismissed) { + popup.hidden = false; + place(trigger, popup); + } + }; + const hideSoon = () => { + clearTimeout(timer); + clearTimeout(hideTimer); + hideTimer = setTimeout(() => { + if (!hovering && root.ownerDocument.activeElement !== trigger) hide(); + }, 300); + }; + on(trigger, "pointerenter", (event) => { + if (event.pointerType !== "touch") { + hovering = true; + dismissed = false; + clearTimeout(hideTimer); + if (popup.hidden) timer = setTimeout(show, 300); + } + }); + on(root, "pointerleave", (event) => { + if (!root.contains(event.relatedTarget)) { + hovering = false; + dismissed = false; + if (root.ownerDocument.activeElement !== trigger) hideSoon(); + } + }); + on(popup, "pointerenter", () => { + hovering = true; + stop(); + }); + on(trigger, "focus", () => { + dismissed = false; + show(); + }); + on(trigger, "blur", () => { + if (!hovering) hide(); + }); + on(trigger, "click", () => { + dismissed = true; + hide(); + }); + on(trigger, "pointerdown", (event) => { + if (event.pointerType === "touch") { + dismissed = false; + timer = setTimeout(show, 500); + } + }); + on(trigger, "pointerup", stop); + on(trigger, "pointercancel", stop); + on(root.ownerDocument, "keydown", (event) => { + if (event.key === "Escape" && !popup.hidden) { + event.preventDefault(); + event.stopImmediatePropagation(); + dismissed = true; + hide(); + } + }, { capture: true }); + on(root.ownerDocument, "scroll", () => { + if (!popup.hidden) place(trigger, popup); + }, { capture: true }); + on(root.ownerDocument.defaultView, "resize", () => { + if (!popup.hidden) place(trigger, popup); + }); + hide(); + return { + show, + hide, + get open() { + return !popup.hidden; + }, + cleanup: hide + }; +} +function popover(root, { on }) { + const trigger = root.querySelector("[data-popover-trigger]"), panel = root.querySelector("[data-popover-panel]"); + if (!trigger || !panel) return {}; + identify(root, panel, "popover"); + trigger.setAttribute("aria-controls", panel.id); + const native = typeof panel.showPopover === "function"; + if (native) { + panel.setAttribute("popover", "auto"); + panel.hidden = false; + } else panel.hidden = true; + let open = false; + const sync = (value) => { + open = value; + trigger.setAttribute("aria-expanded", String(value)); + root.emit("toggle", { expanded: value }); + }; + const show = () => { + if (open || !enabled(trigger)) return; + native ? panel.showPopover() : panel.hidden = false; + sync(true); + place(trigger, panel); + }; + const hide = (focus = false) => { + if (!open) return; + native ? panel.hidePopover() : panel.hidden = true; + sync(false); + if (focus) trigger.focus(); + }; + on(trigger, "click", () => open ? hide() : show()); + on(panel, "beforetoggle", (event) => { + open = event.newState === "open"; + trigger.setAttribute("aria-expanded", String(open)); + }); + on(panel, "click", (event) => { + if (event.target.closest("[data-close]")) hide(true); + }); + on(root.ownerDocument, "pointerdown", (event) => { + if (!native && !root.contains(event.target)) hide(); + }); + on(root, "keydown", (event) => { + if (event.key === "Escape" && open) { + event.preventDefault(); + event.stopPropagation(); + hide(true); + } + }); + on(root.ownerDocument.defaultView, "resize", () => { + if (open) place(trigger, panel); + }); + trigger.setAttribute("aria-expanded", "false"); + return { + show, + hide, + get open() { + return open; + }, + set open(value) { + value ? show() : hide(); + }, + cleanup() { + hide(); + } + }; +} +function feedback(root, { on }) { + const dismiss = (item) => { + if (!item || !root.emit("dismiss", { id: item.id })) return; + const hadFocus = item.contains(root.ownerDocument.activeElement); + const focusable = all(root.ownerDocument, "button,a[href],input,select,textarea,[tabindex='0']").filter((node) => enabled(node) && !node.closest("[hidden]")); + const currentIndex = focusable.indexOf(root.ownerDocument.activeElement); + const next = focusable.slice(currentIndex + 1).find((node) => !item.contains(node)) ?? focusable.slice(0, currentIndex).reverse().find((node) => !item.contains(node)); + item.hidden = true; + if (hadFocus) next?.focus(); + }; + on(root, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button)) return; + if (button.matches(".toast-close,.alert-close,.chip-remove,[data-dismiss]")) dismiss(button.closest(".toast,.alert,.chip") ?? root); + else if (button.matches(".chip-filter")) { + button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); + root.emit("action", { + action: button.textContent.trim(), + pressed: button.getAttribute("aria-pressed") === "true" + }); + } else if (button.matches("[data-retry]")) root.emit("retry", {}); + else root.emit("action", { action: button.dataset.action ?? button.textContent.trim() }); + }); + on(root, "keydown", (event) => { + if (event.key === "Escape") { + const toast = event.target.closest(".toast"); + if (toast) { + event.preventDefault(); + event.stopPropagation(); + dismiss(toast); + } + } + }); + return { dismiss(id) { + dismiss(id ? root.querySelector(`#${CSS.escape(id)}`) : root.querySelector(".toast,.alert") ?? root); + } }; +} +export { tooltip as i, modal as n, popover as r, feedback as t }; diff --git a/packages/ui/dist/copy/tooltip/runtime/chunks/overlays-BwgpF4jI.js b/packages/ui/dist/copy/tooltip/runtime/chunks/overlays-BwgpF4jI.js deleted file mode 100644 index 4b8de2e8b..000000000 --- a/packages/ui/dist/copy/tooltip/runtime/chunks/overlays-BwgpF4jI.js +++ /dev/null @@ -1,245 +0,0 @@ -import { d as place, i as all, o as enabled, s as identify } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/overlays.js -function modal(root, { on }) { - const dialog = root.querySelector("dialog"); - if (!dialog) return {}; - let opener = null; - const show = (trigger = root.ownerDocument.activeElement) => { - if (dialog.open || root.hasAttribute("disabled")) return; - opener = trigger; - dialog.showModal(); - (dialog.querySelector("[autofocus]") ?? dialog.querySelector("button:not(.dialog-button-destructive)"))?.focus(); - root.emit("open", {}); - }; - const close = (value = "") => { - if (dialog.open) dialog.close(String(value)); - }; - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (button?.matches("[data-open]")) { - show(button); - return; - } - if (button && dialog.contains(button) && enabled(button)) { - if (button.matches("[data-close],.dialog-close,.drawer-close")) close(button.dataset.close ?? "cancel"); - else if (button.dataset.action && root.emit("action", { action: button.dataset.action })) close(button.dataset.action); - } - if (root.constructor.componentId === "drawer" && event.target.closest("a[href]") && dialog.contains(event.target)) close("navigate"); - }); - on(dialog, "cancel", (event) => { - if (!root.emit("cancel", {})) event.preventDefault(); - }); - on(dialog, "close", () => { - if (opener?.isConnected) opener.focus(); - root.emit("close", { returnValue: dialog.returnValue }); - }); - return { - show, - close, - get open() { - return dialog.open; - }, - set open(value) { - value ? show() : close(); - }, - get returnValue() { - return dialog.returnValue; - }, - cleanup() { - if (dialog.open) dialog.close(); - } - }; -} -function tooltip(root, { on }) { - const trigger = root.querySelector(".tooltip-trigger"), popup = root.querySelector("[role=\"tooltip\"]"); - if (!trigger || !popup) return {}; - identify(root, popup, "tooltip"); - trigger.setAttribute("aria-describedby", popup.id); - let timer, hideTimer, dismissed = false, hovering = false; - const stop = () => { - clearTimeout(timer); - clearTimeout(hideTimer); - }; - const hide = () => { - stop(); - popup.hidden = true; - }; - const show = () => { - stop(); - if (!dismissed) { - popup.hidden = false; - place(trigger, popup); - } - }; - const hideSoon = () => { - clearTimeout(timer); - clearTimeout(hideTimer); - hideTimer = setTimeout(() => { - if (!hovering && root.ownerDocument.activeElement !== trigger) hide(); - }, 300); - }; - on(trigger, "pointerenter", (event) => { - if (event.pointerType !== "touch") { - hovering = true; - dismissed = false; - clearTimeout(hideTimer); - if (popup.hidden) timer = setTimeout(show, 300); - } - }); - on(root, "pointerleave", (event) => { - if (!root.contains(event.relatedTarget)) { - hovering = false; - dismissed = false; - if (root.ownerDocument.activeElement !== trigger) hideSoon(); - } - }); - on(popup, "pointerenter", () => { - hovering = true; - stop(); - }); - on(trigger, "focus", () => { - dismissed = false; - show(); - }); - on(trigger, "blur", () => { - if (!hovering) hide(); - }); - on(trigger, "click", () => { - dismissed = true; - hide(); - }); - on(trigger, "pointerdown", (event) => { - if (event.pointerType === "touch") { - dismissed = false; - timer = setTimeout(show, 500); - } - }); - on(trigger, "pointerup", stop); - on(trigger, "pointercancel", stop); - on(root.ownerDocument, "keydown", (event) => { - if (event.key === "Escape" && !popup.hidden) { - event.preventDefault(); - event.stopImmediatePropagation(); - dismissed = true; - hide(); - } - }, { capture: true }); - on(root.ownerDocument, "scroll", () => { - if (!popup.hidden) place(trigger, popup); - }, { capture: true }); - on(root.ownerDocument.defaultView, "resize", () => { - if (!popup.hidden) place(trigger, popup); - }); - hide(); - return { - show, - hide, - get open() { - return !popup.hidden; - }, - cleanup: hide - }; -} -function popover(root, { on }) { - const trigger = root.querySelector("[data-popover-trigger]"), panel = root.querySelector("[data-popover-panel]"); - if (!trigger || !panel) return {}; - identify(root, panel, "popover"); - trigger.setAttribute("aria-controls", panel.id); - const native = typeof panel.showPopover === "function"; - if (native) { - panel.setAttribute("popover", "auto"); - panel.hidden = false; - } else panel.hidden = true; - let open = false; - const sync = (value) => { - open = value; - trigger.setAttribute("aria-expanded", String(value)); - root.emit("toggle", { expanded: value }); - }; - const show = () => { - if (open || !enabled(trigger)) return; - native ? panel.showPopover() : panel.hidden = false; - sync(true); - place(trigger, panel); - }; - const hide = (focus = false) => { - if (!open) return; - native ? panel.hidePopover() : panel.hidden = true; - sync(false); - if (focus) trigger.focus(); - }; - on(trigger, "click", () => open ? hide() : show()); - on(panel, "beforetoggle", (event) => { - open = event.newState === "open"; - trigger.setAttribute("aria-expanded", String(open)); - }); - on(panel, "click", (event) => { - if (event.target.closest("[data-close]")) hide(true); - }); - on(root.ownerDocument, "pointerdown", (event) => { - if (!native && !root.contains(event.target)) hide(); - }); - on(root, "keydown", (event) => { - if (event.key === "Escape" && open) { - event.preventDefault(); - event.stopPropagation(); - hide(true); - } - }); - on(root.ownerDocument.defaultView, "resize", () => { - if (open) place(trigger, panel); - }); - trigger.setAttribute("aria-expanded", "false"); - return { - show, - hide, - get open() { - return open; - }, - set open(value) { - value ? show() : hide(); - }, - cleanup() { - hide(); - } - }; -} -function feedback(root, { on }) { - const dismiss = (item) => { - if (!item || !root.emit("dismiss", { id: item.id })) return; - const hadFocus = item.contains(root.ownerDocument.activeElement); - const focusable = all(root.ownerDocument, "button,a[href],input,select,textarea,[tabindex='0']").filter((node) => enabled(node) && !node.closest("[hidden]")); - const currentIndex = focusable.indexOf(root.ownerDocument.activeElement); - const next = focusable.slice(currentIndex + 1).find((node) => !item.contains(node)) ?? focusable.slice(0, currentIndex).reverse().find((node) => !item.contains(node)); - item.hidden = true; - if (hadFocus) next?.focus(); - }; - on(root, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button)) return; - if (button.matches(".toast-close,.alert-close,.chip-remove,[data-dismiss]")) dismiss(button.closest(".toast,.alert,.chip") ?? root); - else if (button.matches(".chip-filter")) { - button.setAttribute("aria-pressed", String(button.getAttribute("aria-pressed") !== "true")); - root.emit("action", { - action: button.textContent.trim(), - pressed: button.getAttribute("aria-pressed") === "true" - }); - } else if (button.matches("[data-retry]")) root.emit("retry", {}); - else root.emit("action", { action: button.dataset.action ?? button.textContent.trim() }); - }); - on(root, "keydown", (event) => { - if (event.key === "Escape") { - const toast = event.target.closest(".toast"); - if (toast) { - event.preventDefault(); - event.stopPropagation(); - dismiss(toast); - } - } - }); - return { dismiss(id) { - dismiss(id ? root.querySelector(`#${CSS.escape(id)}`) : root.querySelector(".toast,.alert") ?? root); - } }; -} -//#endregion -export { tooltip as i, modal as n, popover as r, feedback as t }; diff --git a/packages/ui/dist/copy/tooltip/runtime/components/tooltip.js b/packages/ui/dist/copy/tooltip/runtime/components/tooltip.js index d592891f8..c63418332 100644 --- a/packages/ui/dist/copy/tooltip/runtime/components/tooltip.js +++ b/packages/ui/dist/copy/tooltip/runtime/components/tooltip.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { i as tooltip } from "../chunks/overlays-BwgpF4jI.js"; -//#region .cache/ui-build/entries/components/tooltip.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { i as tooltip } from "../chunks/overlays-BW66WXLm.js"; +// .cache/ui-build/entries/components/tooltip.js var J3w1Tooltip = class extends J3w1Element { static componentId = "tooltip"; static version = "4.0.0"; - static implementationId = "sha256-lBUCe8gBEWWTZ/ovJn9Q/43pRaM2mAdooaxpLQzBDFE="; + static implementationId = "sha256-tg/pFgfIVuB/fXKZ8eGMFx45dRWdM2lYpc9vKsFgM8M="; static connect = tooltip; static upgradeProperties = ["disabled", "name"]; static observedAttributes = [...J3w1Element.observedAttributes, ...["disabled", "loading"]]; @@ -20,5 +20,4 @@ var J3w1Tooltip = class extends J3w1Element { return this._api?.open; } }; -//#endregion export { J3w1Tooltip }; diff --git a/packages/ui/dist/copy/tooltip/runtime/register/tooltip.js b/packages/ui/dist/copy/tooltip/runtime/register/tooltip.js index 262fbe4be..2142a8742 100644 --- a/packages/ui/dist/copy/tooltip/runtime/register/tooltip.js +++ b/packages/ui/dist/copy/tooltip/runtime/register/tooltip.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Tooltip } from "../components/tooltip.js"; -//#region .cache/ui-build/entries/register/tooltip.js +// .cache/ui-build/entries/register/tooltip.js var element = registerElement("j3w1-tooltip", J3w1Tooltip); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/tree/manifest.json b/packages/ui/dist/copy/tree/manifest.json index 1674dca7b..4fa5a7227 100644 --- a/packages/ui/dist/copy/tree/manifest.json +++ b/packages/ui/dist/copy/tree/manifest.json @@ -5,19 +5,19 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/tree.md", "dependencies": [ "register/tree.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/tree.js", - "chunks/advanced-CqBF0dSb.js", - "chunks/markup-DeQ4bEMR.js" + "chunks/advanced-BrFnVc0y.js", + "chunks/markup-AopKpwOF.js" ], "files": { - "runtime/register/tree.js": "sha256-5FC2B/6Dr2k5l/nTb9KKizslYbXmQxe2nEoLuYG6zDg=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/tree.js": "sha256-mYl4DYRuChSjXkRwM7LaJ31aYQZlvzP0RgTYmuNdC9U=", - "runtime/chunks/advanced-CqBF0dSb.js": "sha256-ozOzkRU6IeVGBqU3XQ0aLledkAi9vcs8dJdMQutVevs=", - "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", + "runtime/register/tree.js": "sha256-GkpgoR9dpb/ho4x6diQOMGUvBv63XZ0KfaibFjm74gA=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/tree.js": "sha256-P+63dC5MB2gKl/raxboRMQBCkbmDE850SXCmGt09e/o=", + "runtime/chunks/advanced-BrFnVc0y.js": "sha256-FVberBpKO49P/WGnxa61BTxhYsLnnvMFInur/TwjG44=", + "runtime/chunks/markup-AopKpwOF.js": "sha256-/Dn3cWEmlRQzeQAPVf+C0AooVb1pdIQeNeqd1fQVoPc=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-znFzezcYcv10Qwb2tH/UwaG4XQgCXophAwo2Z8cOiyg=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/tree/runtime/chunks/advanced-BrFnVc0y.js b/packages/ui/dist/copy/tree/runtime/chunks/advanced-BrFnVc0y.js new file mode 100644 index 000000000..36e7638c4 --- /dev/null +++ b/packages/ui/dist/copy/tree/runtime/chunks/advanced-BrFnVc0y.js @@ -0,0 +1,344 @@ +import { c as keyIndex, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-DqwWT5pJ.js"; +import { t as IDREFS } from "./markup-AopKpwOF.js"; +// packages/ui/src/behaviors/advanced.js +function tree(root, { on }) { + const treeRoot = root.querySelector("[role=\"tree\"]"); + if (!treeRoot) return {}; + const items = () => all(treeRoot, "[role=\"treeitem\"]"); + const shown = () => items().filter(visible); + const group = (item) => [...item.children].find((node) => node.getAttribute("role") === "group"); + const parent = (item) => item.parentElement.closest("[role=\"treeitem\"]"); + items().forEach((item, index) => { + identify(root, item, `node-${index}`); + const children = group(item); + if (children) { + if (!item.hasAttribute("aria-expanded")) item.setAttribute("aria-expanded", "false"); + children.hidden = item.getAttribute("aria-expanded") !== "true"; + } + }); + const select = (id) => { + const item = items().find((node) => node.id === id); + if (!item || !enabled(item)) throw new RangeError(`Unknown enabled tree item: ${id}`); + items().forEach((node) => node.setAttribute("aria-selected", String(node === item))); + }; + const expand = (id, expanded = true) => { + const item = items().find((node) => node.id === id), children = item && group(item); + if (!children) throw new RangeError(`Unknown tree parent: ${id}`); + if (!expanded && children.contains(root.ownerDocument.activeElement)) rove(items(), items().indexOf(item)); + item.setAttribute("aria-expanded", String(Boolean(expanded))); + children.hidden = !expanded; + const toggle = item.querySelector(":scope > [data-tree-label] > [data-tree-toggle]"); + if (toggle) toggle.setAttribute("aria-label", expanded ? "Collapse" : "Expand"); + root.emit("toggle", { + id, + expanded: Boolean(expanded) + }); + }; + const activate = (item) => { + if (enabled(item)) { + select(item.id); + root.emit("select", { id: item.id }); + } + }; + const initial = shown(); + rove(initial, Math.max(0, initial.findIndex((item) => item.tabIndex === 0)), false); + on(treeRoot, "click", (event) => { + const item = event.target.closest("[role=\"treeitem\"]"); + if (!item) return; + rove(shown(), shown().indexOf(item)); + if (event.target.closest("[data-tree-toggle]") && group(item)) expand(item.id, item.getAttribute("aria-expanded") !== "true"); + else activate(item); + }); + on(treeRoot, "dblclick", (event) => { + const item = event.target.closest("[role=\"treeitem\"]"); + if (item && group(item) && !event.target.closest("[data-tree-toggle]")) expand(item.id, item.getAttribute("aria-expanded") !== "true"); + }); + on(treeRoot, "keydown", (event) => { + const item = event.target.closest("[role=\"treeitem\"]"); + if (!item) return; + const options = shown(), index = options.indexOf(item), rtl = getComputedStyle(treeRoot).direction === "rtl"; + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const next = keyIndex({ + key: event.key, + index, + length: options.length, + wrap: false + }); + rove(options, next); + } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight")) { + event.preventDefault(); + if (group(item)) { + if (item.getAttribute("aria-expanded") !== "true") expand(item.id); + else rove(shown(), shown().indexOf(item) + 1); + } + } else if (event.key === (rtl ? "ArrowRight" : "ArrowLeft")) { + event.preventDefault(); + if (group(item) && item.getAttribute("aria-expanded") === "true") expand(item.id, false); + else if (parent(item)) rove(options, options.indexOf(parent(item))); + } else if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + activate(item); + } else if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(":scope > [data-tree-label]")?.textContent ?? node.firstChild?.textContent ?? "").trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); + if (found) { + event.preventDefault(); + rove(options, options.indexOf(found)); + } + } + }); + return { + expand, + get selectedId() { + return items().find((item) => item.getAttribute("aria-selected") === "true")?.id ?? ""; + }, + set selectedId(id) { + select(id); + } + }; +} +function multiselect(root, { on, signal }) { + const query = root.querySelector("[data-filter]"), status = root.querySelector("[data-selection-status]"), boxes = all(root, "input[type=\"checkbox\"]"); + const values = () => boxes.filter((box) => box.checked).map((box) => box.value); + const draw = () => { + let matches = 0; + for (const box of boxes) { + const label = box.closest("label"); + if (!label) continue; + label.hidden = !label.textContent.toLocaleLowerCase().includes((query?.value ?? "").toLocaleLowerCase()); + if (!label.hidden) matches++; + } + if (status) status.textContent = `${matches} matching options; ${values().length} selected`; + }; + const report = () => { + draw(); + root.emit("selection", { values: values() }); + }; + const setValues = (selected) => { + if (!Array.isArray(selected) || selected.some((value) => !boxes.some((box) => box.value === value))) throw new TypeError("values must contain known checkbox values"); + boxes.forEach((box) => { + box.checked = selected.includes(box.value); + }); + draw(); + }; + const clear = () => { + if (root.hasAttribute("disabled")) return; + boxes.filter(enabled).forEach((box) => { + if (box.checked) { + box.checked = false; + nativeInput(box); + nativeInput(box, "change"); + } + }); + report(); + }; + on(query, "input", draw); + on(query, "keydown", (event) => { + if (event.key === "Escape" && query.value) { + event.preventDefault(); + event.stopPropagation(); + query.value = ""; + draw(); + } + }); + on(root.querySelector("[data-clear-selection]"), "click", clear); + boxes.forEach((box) => on(box, "change", report)); + on(boxes[0]?.form, "reset", () => queueMicrotask(() => { + if (!signal.aborted) draw(); + })); + draw(); + return { + clear, + get values() { + return values(); + }, + set values(selected) { + setValues(selected); + } + }; +} +function repeater(root, { on }) { + const rows = root.querySelector("[data-rows]"), template = root.querySelector("template[data-row-template]"), addButton = root.querySelector("[data-add]"), status = root.querySelector("[data-repeater-status]"); + if (!rows || !template) return {}; + let sequence = Number(root.dataset.rowSequence ?? 0); + const maximum = () => { + const value = Number(root.getAttribute("max") ?? 10); + if (!Number.isInteger(value) || value < 1 || value > 100) throw new RangeError("max must be an integer from 1 to 100"); + return value; + }; + const children = () => [...rows.children]; + const draw = (message) => { + const items = children(); + if (addButton) addButton.disabled = root.hasAttribute("disabled") || items.length >= maximum(); + const empty = root.querySelector("[data-empty]"); + if (empty) empty.hidden = items.length !== 0; + items.forEach((row, index) => { + all(row, "[data-move]").forEach((button) => { + button.disabled = root.hasAttribute("disabled") || (Number(button.dataset.move) < 0 ? index === 0 : index === items.length - 1); + }); + }); + if (message && status) status.textContent = message; + }; + const report = (message) => { + draw(message); + root.emit("rows", { ids: children().map((row) => row.id) }); + }; + const add = () => { + if (children().length >= maximum() || root.hasAttribute("disabled")) return null; + const row = template.content.firstElementChild.cloneNode(true); + const id = `${root.id}-row-${++sequence}`; + root.dataset.rowSequence = String(sequence); + row.id = id; + const ids = /* @__PURE__ */ new Map(); + all(row, "[id]").forEach((node) => { + ids.set(node.id, `${id}-${node.id}`); + node.id = ids.get(node.id); + }); + for (const node of all(row, "*")) for (const attr of [...node.attributes]) { + if (IDREFS.has(attr.name)) node.setAttribute(attr.name, attr.value.split(/\s+/).map((value) => ids.get(value) ?? value).join(" ")); + if (attr.name === "name") node.name = `${id}[${attr.value}]`; + } + rows.append(row); + report("Row added."); + row.querySelector("input,select,textarea,button")?.focus(); + return id; + }; + const remove = (id) => { + const items = children(), index = items.findIndex((row) => row.id === id); + if (index < 0) throw new RangeError(`Unknown row: ${id}`); + if (root.hasAttribute("disabled")) return; + const hadFocus = items[index].contains(root.ownerDocument.activeElement); + items[index].remove(); + report("Row removed."); + if (hadFocus) (children()[Math.min(index, children().length - 1)]?.querySelector("input,select,textarea,button") ?? addButton)?.focus(); + }; + const move = (id, direction) => { + if (![-1, 1].includes(direction)) throw new RangeError("direction must be -1 or 1"); + const items = children(), index = items.findIndex((row) => row.id === id), target = index + direction; + if (index < 0) throw new RangeError(`Unknown row: ${id}`); + if (target < 0 || target >= items.length || root.hasAttribute("disabled")) return; + const focused = root.ownerDocument.activeElement; + if (direction < 0) rows.insertBefore(items[index], items[target]); + else rows.insertBefore(items[target], items[index]); + report(direction < 0 ? "Row moved up." : "Row moved down."); + if (items[index].contains(focused) && !focused.disabled) focused.focus(); + else items[index].querySelector("input,select,textarea,button:not(:disabled)")?.focus(); + }; + on(addButton, "click", add); + on(rows, "click", (event) => { + const button = event.target.closest("button"); + if (!button || !enabled(button)) return; + const row = children().find((item) => item.contains(button)); + if (button.hasAttribute("data-remove")) remove(row.id); + else if (button.hasAttribute("data-move")) move(row.id, Number(button.dataset.move)); + }); + draw(); + return { + add, + remove, + move, + get rowIds() { + return children().map((row) => row.id); + }, + attributeChanged() { + draw(); + } + }; +} +function commandPalette(root, { on }) { + const dialog = root.querySelector("dialog"), input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"), status = root.querySelector("[data-command-status]"); + if (!dialog || !input || !list) return {}; + let opener, active = null; + all(list, "[role=\"option\"]").forEach((option, index) => { + identify(root, option, `command-${index}`); + option.tabIndex = -1; + }); + const options = () => all(list, "[role=\"option\"]").filter((option) => enabled(option) && !option.hidden); + const select = (option) => { + active = option; + all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); + if (option) { + input.setAttribute("aria-activedescendant", option.id); + option.scrollIntoView({ block: "nearest" }); + } else input.removeAttribute("aria-activedescendant"); + }; + const filter = () => { + all(list, "[role=\"option\"]").forEach((option) => { + option.hidden = !option.textContent.toLocaleLowerCase().includes(input.value.toLocaleLowerCase()); + }); + select(options()[0] ?? null); + if (status) status.textContent = `${options().length} commands`; + }; + const show = (trigger = root.ownerDocument.activeElement) => { + if (dialog.open || root.hasAttribute("disabled")) return; + opener = trigger; + dialog.showModal(); + filter(); + input.focus(); + }; + const close = () => { + if (dialog.open) dialog.close(); + }; + const invoke = (option) => { + if (!option || !enabled(option)) return; + const link = option.matches("a[href]") ? option : option.querySelector("a[href]"); + const proceed = root.emit("command", { + action: option.dataset.action ?? option.id, + href: link?.getAttribute("href") ?? null + }); + close(); + if (proceed && link) root.ownerDocument.defaultView.location.assign(link.href); + }; + on(root, "click", (event) => { + const trigger = event.target.closest("[data-open]"); + if (trigger) show(trigger); + else if (event.target.closest("[data-close]")) close(); + else { + const option = event.target.closest("[role=\"option\"]"); + if (option) { + event.preventDefault(); + invoke(option); + } + } + }); + on(input, "input", filter); + on(input, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + close(); + } else if (["ArrowDown", "ArrowUp"].includes(event.key)) { + event.preventDefault(); + const items = options(), index = items.indexOf(active); + if (items.length) select(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); + } else if (event.key === "Enter") { + event.preventDefault(); + invoke(active); + } + }); + on(dialog, "close", () => { + if (opener?.isConnected) opener.focus(); + }); + on(root.ownerDocument, "keydown", (event) => { + if (root.hasAttribute("shortcut") && (event.ctrlKey || event.metaKey) && !event.altKey && event.key.toLowerCase() === "k" && !event.defaultPrevented) { + event.preventDefault(); + dialog.open ? close() : show(); + } + }); + return { + show, + close, + get open() { + return dialog.open; + }, + set open(value) { + value ? show() : close(); + }, + cleanup: close + }; +} +export { tree as i, multiselect as n, repeater as r, commandPalette as t }; diff --git a/packages/ui/dist/copy/tree/runtime/chunks/advanced-CqBF0dSb.js b/packages/ui/dist/copy/tree/runtime/chunks/advanced-CqBF0dSb.js deleted file mode 100644 index 4a5c45981..000000000 --- a/packages/ui/dist/copy/tree/runtime/chunks/advanced-CqBF0dSb.js +++ /dev/null @@ -1,345 +0,0 @@ -import { c as keyIndex, f as rove, i as all, o as enabled, p as visible, s as identify, u as nativeInput } from "./choice-B7mo5Eq3.js"; -import { t as IDREFS } from "./markup-DeQ4bEMR.js"; -//#region packages/ui/src/behaviors/advanced.js -function tree(root, { on }) { - const treeRoot = root.querySelector("[role=\"tree\"]"); - if (!treeRoot) return {}; - const items = () => all(treeRoot, "[role=\"treeitem\"]"); - const shown = () => items().filter(visible); - const group = (item) => [...item.children].find((node) => node.getAttribute("role") === "group"); - const parent = (item) => item.parentElement.closest("[role=\"treeitem\"]"); - items().forEach((item, index) => { - identify(root, item, `node-${index}`); - const children = group(item); - if (children) { - if (!item.hasAttribute("aria-expanded")) item.setAttribute("aria-expanded", "false"); - children.hidden = item.getAttribute("aria-expanded") !== "true"; - } - }); - const select = (id) => { - const item = items().find((node) => node.id === id); - if (!item || !enabled(item)) throw new RangeError(`Unknown enabled tree item: ${id}`); - items().forEach((node) => node.setAttribute("aria-selected", String(node === item))); - }; - const expand = (id, expanded = true) => { - const item = items().find((node) => node.id === id), children = item && group(item); - if (!children) throw new RangeError(`Unknown tree parent: ${id}`); - if (!expanded && children.contains(root.ownerDocument.activeElement)) rove(items(), items().indexOf(item)); - item.setAttribute("aria-expanded", String(Boolean(expanded))); - children.hidden = !expanded; - const toggle = item.querySelector(":scope > [data-tree-label] > [data-tree-toggle]"); - if (toggle) toggle.setAttribute("aria-label", expanded ? "Collapse" : "Expand"); - root.emit("toggle", { - id, - expanded: Boolean(expanded) - }); - }; - const activate = (item) => { - if (enabled(item)) { - select(item.id); - root.emit("select", { id: item.id }); - } - }; - const initial = shown(); - rove(initial, Math.max(0, initial.findIndex((item) => item.tabIndex === 0)), false); - on(treeRoot, "click", (event) => { - const item = event.target.closest("[role=\"treeitem\"]"); - if (!item) return; - rove(shown(), shown().indexOf(item)); - if (event.target.closest("[data-tree-toggle]") && group(item)) expand(item.id, item.getAttribute("aria-expanded") !== "true"); - else activate(item); - }); - on(treeRoot, "dblclick", (event) => { - const item = event.target.closest("[role=\"treeitem\"]"); - if (item && group(item) && !event.target.closest("[data-tree-toggle]")) expand(item.id, item.getAttribute("aria-expanded") !== "true"); - }); - on(treeRoot, "keydown", (event) => { - const item = event.target.closest("[role=\"treeitem\"]"); - if (!item) return; - const options = shown(), index = options.indexOf(item), rtl = getComputedStyle(treeRoot).direction === "rtl"; - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const next = keyIndex({ - key: event.key, - index, - length: options.length, - wrap: false - }); - rove(options, next); - } else if (event.key === (rtl ? "ArrowLeft" : "ArrowRight")) { - event.preventDefault(); - if (group(item)) { - if (item.getAttribute("aria-expanded") !== "true") expand(item.id); - else rove(shown(), shown().indexOf(item) + 1); - } - } else if (event.key === (rtl ? "ArrowRight" : "ArrowLeft")) { - event.preventDefault(); - if (group(item) && item.getAttribute("aria-expanded") === "true") expand(item.id, false); - else if (parent(item)) rove(options, options.indexOf(parent(item))); - } else if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - activate(item); - } else if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - const found = [...options.slice(index + 1), ...options.slice(0, index + 1)].find((node) => (node.querySelector(":scope > [data-tree-label]")?.textContent ?? node.firstChild?.textContent ?? "").trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase())); - if (found) { - event.preventDefault(); - rove(options, options.indexOf(found)); - } - } - }); - return { - expand, - get selectedId() { - return items().find((item) => item.getAttribute("aria-selected") === "true")?.id ?? ""; - }, - set selectedId(id) { - select(id); - } - }; -} -function multiselect(root, { on, signal }) { - const query = root.querySelector("[data-filter]"), status = root.querySelector("[data-selection-status]"), boxes = all(root, "input[type=\"checkbox\"]"); - const values = () => boxes.filter((box) => box.checked).map((box) => box.value); - const draw = () => { - let matches = 0; - for (const box of boxes) { - const label = box.closest("label"); - if (!label) continue; - label.hidden = !label.textContent.toLocaleLowerCase().includes((query?.value ?? "").toLocaleLowerCase()); - if (!label.hidden) matches++; - } - if (status) status.textContent = `${matches} matching options; ${values().length} selected`; - }; - const report = () => { - draw(); - root.emit("selection", { values: values() }); - }; - const setValues = (selected) => { - if (!Array.isArray(selected) || selected.some((value) => !boxes.some((box) => box.value === value))) throw new TypeError("values must contain known checkbox values"); - boxes.forEach((box) => { - box.checked = selected.includes(box.value); - }); - draw(); - }; - const clear = () => { - if (root.hasAttribute("disabled")) return; - boxes.filter(enabled).forEach((box) => { - if (box.checked) { - box.checked = false; - nativeInput(box); - nativeInput(box, "change"); - } - }); - report(); - }; - on(query, "input", draw); - on(query, "keydown", (event) => { - if (event.key === "Escape" && query.value) { - event.preventDefault(); - event.stopPropagation(); - query.value = ""; - draw(); - } - }); - on(root.querySelector("[data-clear-selection]"), "click", clear); - boxes.forEach((box) => on(box, "change", report)); - on(boxes[0]?.form, "reset", () => queueMicrotask(() => { - if (!signal.aborted) draw(); - })); - draw(); - return { - clear, - get values() { - return values(); - }, - set values(selected) { - setValues(selected); - } - }; -} -function repeater(root, { on }) { - const rows = root.querySelector("[data-rows]"), template = root.querySelector("template[data-row-template]"), addButton = root.querySelector("[data-add]"), status = root.querySelector("[data-repeater-status]"); - if (!rows || !template) return {}; - let sequence = Number(root.dataset.rowSequence ?? 0); - const maximum = () => { - const value = Number(root.getAttribute("max") ?? 10); - if (!Number.isInteger(value) || value < 1 || value > 100) throw new RangeError("max must be an integer from 1 to 100"); - return value; - }; - const children = () => [...rows.children]; - const draw = (message) => { - const items = children(); - if (addButton) addButton.disabled = root.hasAttribute("disabled") || items.length >= maximum(); - const empty = root.querySelector("[data-empty]"); - if (empty) empty.hidden = items.length !== 0; - items.forEach((row, index) => { - all(row, "[data-move]").forEach((button) => { - button.disabled = root.hasAttribute("disabled") || (Number(button.dataset.move) < 0 ? index === 0 : index === items.length - 1); - }); - }); - if (message && status) status.textContent = message; - }; - const report = (message) => { - draw(message); - root.emit("rows", { ids: children().map((row) => row.id) }); - }; - const add = () => { - if (children().length >= maximum() || root.hasAttribute("disabled")) return null; - const row = template.content.firstElementChild.cloneNode(true); - const id = `${root.id}-row-${++sequence}`; - root.dataset.rowSequence = String(sequence); - row.id = id; - const ids = /* @__PURE__ */ new Map(); - all(row, "[id]").forEach((node) => { - ids.set(node.id, `${id}-${node.id}`); - node.id = ids.get(node.id); - }); - for (const node of all(row, "*")) for (const attr of [...node.attributes]) { - if (IDREFS.has(attr.name)) node.setAttribute(attr.name, attr.value.split(/\s+/).map((value) => ids.get(value) ?? value).join(" ")); - if (attr.name === "name") node.name = `${id}[${attr.value}]`; - } - rows.append(row); - report("Row added."); - row.querySelector("input,select,textarea,button")?.focus(); - return id; - }; - const remove = (id) => { - const items = children(), index = items.findIndex((row) => row.id === id); - if (index < 0) throw new RangeError(`Unknown row: ${id}`); - if (root.hasAttribute("disabled")) return; - const hadFocus = items[index].contains(root.ownerDocument.activeElement); - items[index].remove(); - report("Row removed."); - if (hadFocus) (children()[Math.min(index, children().length - 1)]?.querySelector("input,select,textarea,button") ?? addButton)?.focus(); - }; - const move = (id, direction) => { - if (![-1, 1].includes(direction)) throw new RangeError("direction must be -1 or 1"); - const items = children(), index = items.findIndex((row) => row.id === id), target = index + direction; - if (index < 0) throw new RangeError(`Unknown row: ${id}`); - if (target < 0 || target >= items.length || root.hasAttribute("disabled")) return; - const focused = root.ownerDocument.activeElement; - if (direction < 0) rows.insertBefore(items[index], items[target]); - else rows.insertBefore(items[target], items[index]); - report(direction < 0 ? "Row moved up." : "Row moved down."); - if (items[index].contains(focused) && !focused.disabled) focused.focus(); - else items[index].querySelector("input,select,textarea,button:not(:disabled)")?.focus(); - }; - on(addButton, "click", add); - on(rows, "click", (event) => { - const button = event.target.closest("button"); - if (!button || !enabled(button)) return; - const row = children().find((item) => item.contains(button)); - if (button.hasAttribute("data-remove")) remove(row.id); - else if (button.hasAttribute("data-move")) move(row.id, Number(button.dataset.move)); - }); - draw(); - return { - add, - remove, - move, - get rowIds() { - return children().map((row) => row.id); - }, - attributeChanged() { - draw(); - } - }; -} -function commandPalette(root, { on }) { - const dialog = root.querySelector("dialog"), input = root.querySelector("input[role=\"combobox\"]"), list = root.querySelector("[role=\"listbox\"]"), status = root.querySelector("[data-command-status]"); - if (!dialog || !input || !list) return {}; - let opener, active = null; - all(list, "[role=\"option\"]").forEach((option, index) => { - identify(root, option, `command-${index}`); - option.tabIndex = -1; - }); - const options = () => all(list, "[role=\"option\"]").filter((option) => enabled(option) && !option.hidden); - const select = (option) => { - active = option; - all(list, "[role=\"option\"]").forEach((node) => node.setAttribute("aria-selected", String(node === option))); - if (option) { - input.setAttribute("aria-activedescendant", option.id); - option.scrollIntoView({ block: "nearest" }); - } else input.removeAttribute("aria-activedescendant"); - }; - const filter = () => { - all(list, "[role=\"option\"]").forEach((option) => { - option.hidden = !option.textContent.toLocaleLowerCase().includes(input.value.toLocaleLowerCase()); - }); - select(options()[0] ?? null); - if (status) status.textContent = `${options().length} commands`; - }; - const show = (trigger = root.ownerDocument.activeElement) => { - if (dialog.open || root.hasAttribute("disabled")) return; - opener = trigger; - dialog.showModal(); - filter(); - input.focus(); - }; - const close = () => { - if (dialog.open) dialog.close(); - }; - const invoke = (option) => { - if (!option || !enabled(option)) return; - const link = option.matches("a[href]") ? option : option.querySelector("a[href]"); - const proceed = root.emit("command", { - action: option.dataset.action ?? option.id, - href: link?.getAttribute("href") ?? null - }); - close(); - if (proceed && link) root.ownerDocument.defaultView.location.assign(link.href); - }; - on(root, "click", (event) => { - const trigger = event.target.closest("[data-open]"); - if (trigger) show(trigger); - else if (event.target.closest("[data-close]")) close(); - else { - const option = event.target.closest("[role=\"option\"]"); - if (option) { - event.preventDefault(); - invoke(option); - } - } - }); - on(input, "input", filter); - on(input, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - close(); - } else if (["ArrowDown", "ArrowUp"].includes(event.key)) { - event.preventDefault(); - const items = options(), index = items.indexOf(active); - if (items.length) select(items[(index + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length]); - } else if (event.key === "Enter") { - event.preventDefault(); - invoke(active); - } - }); - on(dialog, "close", () => { - if (opener?.isConnected) opener.focus(); - }); - on(root.ownerDocument, "keydown", (event) => { - if (root.hasAttribute("shortcut") && (event.ctrlKey || event.metaKey) && !event.altKey && event.key.toLowerCase() === "k" && !event.defaultPrevented) { - event.preventDefault(); - dialog.open ? close() : show(); - } - }); - return { - show, - close, - get open() { - return dialog.open; - }, - set open(value) { - value ? show() : close(); - }, - cleanup: close - }; -} -//#endregion -export { tree as i, multiselect as n, repeater as r, commandPalette as t }; diff --git a/packages/ui/dist/copy/tree/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/tree/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/tree/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/tree/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/tree/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/tree/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/tree/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/tree/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/tree/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/tree/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/tree/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/tree/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/tree/runtime/chunks/markup-AopKpwOF.js b/packages/ui/dist/copy/tree/runtime/chunks/markup-AopKpwOF.js new file mode 100644 index 000000000..bc1c52c0b --- /dev/null +++ b/packages/ui/dist/copy/tree/runtime/chunks/markup-AopKpwOF.js @@ -0,0 +1,53 @@ +// scripts/lib/markup.mjs +var IDREFS = /* @__PURE__ */ new Set([ + "for", + "form", + "list", + "aria-labelledby", + "aria-describedby", + "aria-controls", + "aria-owns", + "aria-activedescendant", + "aria-details", + "aria-errormessage", + "headers" +]); +var walkMarkup = (node, visit) => { + visit(node); + for (const child of node.childNodes ?? []) walkMarkup(child, visit); + if (node.tagName === "template" && node.content) walkMarkup(node.content, visit); +}; +var attribute = (node, name) => node.attrs?.find((a) => a.name === name)?.value; +var setAttribute = (node, name, value = "") => { + if (!node?.attrs) return; + const current = node.attrs.find((a) => a.name === name); + if (current) current.value = value; + else node.attrs.push({ + name, + value + }); +}; +var removeAttribute = (node, name) => { + if (node.attrs) node.attrs = node.attrs.filter((a) => a.name !== name); +}; +var hasClass = (node, name) => attribute(node, "class")?.split(/\s+/).includes(name) ?? false; +var namespaceMarkup = (tree, decorate, { strict = true, renameNames = false } = {}) => { + const ids = /* @__PURE__ */ new Map(); + walkMarkup(tree, (node) => { + const id = attribute(node, "id"); + if (id === void 0) return; + if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(id) || ids.has(id)) throw new Error(`Invalid or duplicate markup ID: ${id}`); + ids.set(id, decorate(id)); + }); + const reference = (id) => { + if (!ids.has(id) && strict) throw new Error(`Unresolved markup ID reference: ${id}`); + return ids.get(id) ?? decorate(id); + }; + walkMarkup(tree, (node) => { + for (const attr of node.attrs ?? []) if (attr.name === "id") attr.value = reference(attr.value); + else if (IDREFS.has(attr.name)) attr.value = attr.value.trim().split(/\s+/).map(reference).join(" "); + else if (attr.name === "href" && attr.value.startsWith("#")) attr.value = `#${reference(attr.value.slice(1))}`; + else if (renameNames && attr.name === "name") attr.value = decorate(attr.value); + }); +}; +export { setAttribute as a, removeAttribute as i, hasClass as n, walkMarkup as o, namespaceMarkup as r, IDREFS as t }; diff --git a/packages/ui/dist/copy/tree/runtime/chunks/markup-DeQ4bEMR.js b/packages/ui/dist/copy/tree/runtime/chunks/markup-DeQ4bEMR.js deleted file mode 100644 index 77bd9471d..000000000 --- a/packages/ui/dist/copy/tree/runtime/chunks/markup-DeQ4bEMR.js +++ /dev/null @@ -1,54 +0,0 @@ -//#region scripts/lib/markup.mjs -var IDREFS = /* @__PURE__ */ new Set([ - "for", - "form", - "list", - "aria-labelledby", - "aria-describedby", - "aria-controls", - "aria-owns", - "aria-activedescendant", - "aria-details", - "aria-errormessage", - "headers" -]); -var walkMarkup = (node, visit) => { - visit(node); - for (const child of node.childNodes ?? []) walkMarkup(child, visit); - if (node.tagName === "template" && node.content) walkMarkup(node.content, visit); -}; -var attribute = (node, name) => node.attrs?.find((a) => a.name === name)?.value; -var setAttribute = (node, name, value = "") => { - if (!node?.attrs) return; - const current = node.attrs.find((a) => a.name === name); - if (current) current.value = value; - else node.attrs.push({ - name, - value - }); -}; -var removeAttribute = (node, name) => { - if (node.attrs) node.attrs = node.attrs.filter((a) => a.name !== name); -}; -var hasClass = (node, name) => attribute(node, "class")?.split(/\s+/).includes(name) ?? false; -var namespaceMarkup = (tree, decorate, { strict = true, renameNames = false } = {}) => { - const ids = /* @__PURE__ */ new Map(); - walkMarkup(tree, (node) => { - const id = attribute(node, "id"); - if (id === void 0) return; - if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(id) || ids.has(id)) throw new Error(`Invalid or duplicate markup ID: ${id}`); - ids.set(id, decorate(id)); - }); - const reference = (id) => { - if (!ids.has(id) && strict) throw new Error(`Unresolved markup ID reference: ${id}`); - return ids.get(id) ?? decorate(id); - }; - walkMarkup(tree, (node) => { - for (const attr of node.attrs ?? []) if (attr.name === "id") attr.value = reference(attr.value); - else if (IDREFS.has(attr.name)) attr.value = attr.value.trim().split(/\s+/).map(reference).join(" "); - else if (attr.name === "href" && attr.value.startsWith("#")) attr.value = `#${reference(attr.value.slice(1))}`; - else if (renameNames && attr.name === "name") attr.value = decorate(attr.value); - }); -}; -//#endregion -export { setAttribute as a, removeAttribute as i, hasClass as n, walkMarkup as o, namespaceMarkup as r, IDREFS as t }; diff --git a/packages/ui/dist/copy/tree/runtime/components/tree.js b/packages/ui/dist/copy/tree/runtime/components/tree.js index e0f6bd8da..d64ee41f2 100644 --- a/packages/ui/dist/copy/tree/runtime/components/tree.js +++ b/packages/ui/dist/copy/tree/runtime/components/tree.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { i as tree } from "../chunks/advanced-CqBF0dSb.js"; -//#region .cache/ui-build/entries/components/tree.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { i as tree } from "../chunks/advanced-BrFnVc0y.js"; +// .cache/ui-build/entries/components/tree.js var J3w1Tree = class extends J3w1Element { static componentId = "tree"; static version = "4.0.0"; - static implementationId = "sha256-8E6bGMMWEmhgjIAfuDs1+pxcabRicShQao3beIvcNBY="; + static implementationId = "sha256-4tyCeiJO1ktFeL6tRtS1nNUZhSguTNcVzLun9Gw4gX0="; static connect = tree; static upgradeProperties = [ "disabled", @@ -28,5 +28,4 @@ var J3w1Tree = class extends J3w1Element { }); } }; -//#endregion export { J3w1Tree }; diff --git a/packages/ui/dist/copy/tree/runtime/register/tree.js b/packages/ui/dist/copy/tree/runtime/register/tree.js index 0ecee9bca..eb6e73696 100644 --- a/packages/ui/dist/copy/tree/runtime/register/tree.js +++ b/packages/ui/dist/copy/tree/runtime/register/tree.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Tree } from "../components/tree.js"; -//#region .cache/ui-build/entries/register/tree.js +// .cache/ui-build/entries/register/tree.js var element = registerElement("j3w1-tree", J3w1Tree); -//#endregion export { element }; diff --git a/packages/ui/dist/copy/wizard/manifest.json b/packages/ui/dist/copy/wizard/manifest.json index ce3b2fa64..1ff2385a6 100644 --- a/packages/ui/dist/copy/wizard/manifest.json +++ b/packages/ui/dist/copy/wizard/manifest.json @@ -5,17 +5,17 @@ "contract": "https://github.com/j3w1/theme/blob/v4.0.0/spec/components/wizard.md", "dependencies": [ "register/wizard.js", - "chunks/element-Dovcr9Ky.js", - "chunks/choice-B7mo5Eq3.js", + "chunks/element-DcrNU9Wh.js", + "chunks/choice-DqwWT5pJ.js", "components/wizard.js", - "chunks/forms-CE_hP1hg.js" + "chunks/forms-C3u5121t.js" ], "files": { - "runtime/register/wizard.js": "sha256-j1MmLx8Vq3Ou/t3+hX/UD2AWZq1D7MRHwwvCLStmpFw=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/wizard.js": "sha256-iMzWia0NibbI8OZR3lt0VNBXQXq/OjK7Mz8n9BHkt5c=", - "runtime/chunks/forms-CE_hP1hg.js": "sha256-uOnoMuSkUbm9C/GfR+PDLYCykyHOQ1Ni7g59c4YMOS0=", + "runtime/register/wizard.js": "sha256-3aACVGrEwAij3/eXLo2Kj2WGiM2PDHgexOEY8UmD/ro=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/wizard.js": "sha256-qUPBej2sL10ar6pmuJhdA1Tk155stiGvejFAN+ep+P4=", + "runtime/chunks/forms-C3u5121t.js": "sha256-DymhKeiaCcQj+DmkDxoEwP0Md4YxiSpCxyYS4eiMnV0=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-DfWE/GpjBHHnAxchKcu5pTgCo39mSS+V9uDHjFqFwmA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", diff --git a/packages/ui/dist/copy/wizard/runtime/chunks/choice-B7mo5Eq3.js b/packages/ui/dist/copy/wizard/runtime/chunks/choice-B7mo5Eq3.js deleted file mode 100644 index 849c80b8b..000000000 --- a/packages/ui/dist/copy/wizard/runtime/chunks/choice-B7mo5Eq3.js +++ /dev/null @@ -1,938 +0,0 @@ -//#region packages/ui/src/internal/dom.js -var all = (root, selector) => [...root.querySelectorAll(selector)]; -var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; -var visible = (node) => !node.closest("[hidden]"); -function controlLabelText(labels) { - const text = (node) => { - if (node.nodeType === 3) return node.textContent; - if (node.nodeType !== 1) return ""; - if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; - const style = node.ownerDocument.defaultView.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden") return ""; - return [...node.childNodes].map(text).join(""); - }; - return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); -} -function announce(root, message) { - let status = root.querySelector("[data-j3w1-status]"); - if (!status) { - status = root.ownerDocument.createElement("p"); - status.dataset.j3w1Status = ""; - status.className = "j3w1-visually-hidden"; - status.setAttribute("role", "status"); - root.append(status); - } - status.textContent = message; -} -function identify(root, node, suffix) { - if (node && !node.id) node.id = `${root.id}-${suffix}`; - return node?.id; -} -function nativeInput(input, type = "input") { - input.dispatchEvent(new Event(type, { bubbles: true })); -} -function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { - if (key === "Home") return 0; - if (key === "End") return length - 1; - const target = index + (key === next ? 1 : key === previous ? -1 : 0); - return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); -} -function rove(items, index, focus = true) { - if (!items.length) return null; - const next = items[(index + items.length) % items.length]; - items.forEach((item) => { - item.tabIndex = item === next ? 0 : -1; - }); - if (focus) next.focus(); - return next; -} -function make(root, tag, attrs = {}, text) { - const node = root.ownerDocument.createElement(tag); - for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); - if (text !== void 0) node.textContent = String(text); - return node; -} -function makeIcon(root, d, attrs = {}) { - const ns = "http://www.w3.org/2000/svg"; - const svg = root.ownerDocument.createElementNS(ns, "svg"); - for (const [key, value] of Object.entries({ - viewBox: "0 0 16 16", - width: "16", - height: "16", - "aria-hidden": "true", - focusable: "false", - ...attrs - })) svg.setAttribute(key, String(value)); - const path = root.ownerDocument.createElementNS(ns, "path"); - for (const [key, value] of Object.entries({ - d, - fill: "none", - stroke: "currentColor", - "stroke-width": "1.5" - })) path.setAttribute(key, value); - svg.append(path); - return svg; -} -function place(trigger, popup) { - const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); - const doc = trigger.ownerDocument.documentElement; - const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); - const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; - Object.assign(popup.style, { - position: "fixed", - insetInlineStart: "auto", - insetInlineEnd: "auto", - left: `${left}px`, - top: `${top}px`, - maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, - overflowY: "auto" - }); -} -//#endregion -//#region packages/ui/src/internal/temporal.js -var instances = /* @__PURE__ */ new WeakMap(); -var sequence$1 = 0; -function mountTemporal(input) { - if (instances.has(input)) return instances.get(input); - const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); - const numeric = (value) => { - if (date) { - if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; - const stamp = Date.parse(`${value}T00:00:00Z`); - return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; - } - const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); - if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; - return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); - }; - const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; - const constraint = (value) => { - const number = numeric(value), min = numeric(input.min), max = numeric(input.max); - if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; - if (!date && min > max) { - if (number < min && number > max) return "Choose a time within the allowed range."; - } else if (number < min || number > max) return "Choose a value within the allowed range."; - const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; - if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; - return ""; - }; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - let id; - do - id = `j3w1-temporal-${++sequence$1}`; - while (input.ownerDocument.getElementById(`${id}-input`)); - const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); - const editor = make(input, "input", { - id: `${id}-input`, - type: "text", - class: "j3w1-temporal-input", - autocomplete: "off", - placeholder: date ? "YYYY-MM-DD" : "HH:MM", - inputmode: "text" - }); - const message = make(input, "span", { - id: `${id}-error`, - class: "j3w1-choice-error", - role: "status", - hidden: "" - }); - const popup = make(input, "span", { - class: "j3w1-calendar", - role: "dialog", - "aria-modal": "false", - "aria-label": "Choose date", - popover: "manual", - hidden: "" - }); - const opener = make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": date ? "Open calendar" : "Increase time" - }, date ? "▦" : "+"); - row.append(editor, opener); - const decrease = date ? null : make(input, "button", { - type: "button", - class: "j3w1-temporal-action", - "aria-label": "Decrease time" - }, "−"); - if (decrease) row.append(decrease); - shell.append(row, message); - if (date) shell.append(popup); - input.after(shell); - const labels = [...input.labels ?? []]; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = editor.id; - restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const attributes = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, input.getAttribute(name)])); - input.hidden = true; - input.setAttribute("aria-hidden", "true"); - input.tabIndex = -1; - let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; - const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; - const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); - const labelText = () => controlLabelText(labels); - const close = (focus = false) => { - if (popup.matches(":popover-open")) popup.hidePopover(); - popup.hidden = true; - open = false; - opener.setAttribute("aria-expanded", "false"); - if (focus) editor.focus(); - }; - const sync = () => { - if (abort.signal.aborted) return; - if (!writing) editor.value = input.value; - editor.disabled = input.matches(":disabled"); - editor.readOnly = input.readOnly; - editor.required = input.required; - if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); - else editor.removeAttribute("form"); - opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; - if (decrease) decrease.disabled = opener.disabled; - if (opener.disabled) close(); - const labelled = input.getAttribute("aria-labelledby"); - if (labelled) { - editor.setAttribute("aria-labelledby", labelled); - editor.removeAttribute("aria-label"); - } else { - editor.removeAttribute("aria-labelledby"); - editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); - } - if (!nativeTemporal) { - if (input.validationMessage === fallbackError) input.setCustomValidity(""); - fallbackError = constraint(editor.value); - if (!input.validationMessage) input.setCustomValidity(fallbackError); - } - const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); - editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); - const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; - editor.setAttribute("aria-invalid", String(invalid)); - message.hidden = !invalid; - message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; - const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; - if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { - class: "j3w1-temporal-hint", - id: `${id}-hint` - }, described[1])); - editor.setAttribute("aria-describedby", [ - described[0], - `${id}-hint`, - invalid ? message.id : "" - ].filter(Boolean).join(" ")); - }; - const write = (value, change = false) => { - writing = true; - editor.value = value; - input.value = Number.isFinite(numeric(value)) ? value : ""; - nativeInput(input); - if (change) { - touched = true; - nativeInput(input, "change"); - } - sync(); - writing = false; - }; - const enabledDay = (value) => !constraint(value); - const draw = () => { - popup.replaceChildren(); - const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { - type: "button", - "data-month": "-1", - "aria-label": "Previous month" - }, "←"), next = make(input, "button", { - type: "button", - "data-month": "1", - "aria-label": "Next month" - }, "→"); - const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { - month: "long", - year: "numeric" - })); - heading.append(previous, title, next); - popup.append(heading); - const grid = make(input, "span", { - role: "grid", - "aria-labelledby": title.id, - class: "j3w1-calendar-grid" - }); - const header = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - for (const day of [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ]) header.append(make(input, "span", { role: "columnheader" }, day)); - grid.append(header); - const first = new Date(view); - first.setDate(1); - const last = new Date(first); - last.setMonth(last.getMonth() + 1); - last.setDate(0); - let week; - for (let index = 0; index < first.getDay() + last.getDate(); index++) { - if (index % 7 === 0) { - week = make(input, "span", { - role: "row", - class: "j3w1-calendar-week" - }); - grid.append(week); - } - const cell = make(input, "span", { role: "gridcell" }); - week.append(cell); - const day = index - first.getDay() + 1; - if (day < 1) continue; - const current = new Date(first); - current.setDate(day); - const value = format(current), button = make(input, "button", { - type: "button", - "data-date": value, - tabindex: value === activeDay ? "0" : "-1", - "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), - "aria-pressed": String(value === input.value) - }, day); - button.disabled = !enabledDay(value); - cell.append(button); - } - popup.append(grid); - if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { - const first = popup.querySelector("button[data-date]:not(:disabled)"); - if (first) { - first.tabIndex = 0; - activeDay = first.dataset.date; - } - } - if (open) place(opener, popup); - }; - const show = () => { - if (opener.disabled) return; - const selected = parse(input.value); - view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; - activeDay = format(view); - open = true; - popup.hidden = false; - opener.setAttribute("aria-expanded", "true"); - draw(); - if (typeof popup.showPopover === "function") popup.showPopover(); - place(opener, popup); - popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); - }; - if (date) { - opener.setAttribute("aria-haspopup", "dialog"); - opener.setAttribute("aria-expanded", "false"); - on(opener, "click", () => open ? close(true) : show()); - } else { - const step = (amount) => { - if (nativeTemporal) { - amount > 0 ? input.stepUp() : input.stepDown(); - write(input.value, true); - } else { - const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; - const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; - if (value >= 0 && value < 86400) { - const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); - const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; - if (!constraint(text)) write(text, true); - } - } - editor.focus(); - }; - on(opener, "click", () => step(1)); - on(decrease, "click", () => step(-1)); - } - on(editor, "input", (event) => { - event.stopPropagation(); - write(editor.value); - }); - on(editor, "change", (event) => { - event.stopPropagation(); - write(editor.value, true); - }); - for (const control of [editor, input]) on(control, "invalid", (event) => { - event.preventDefault(); - touched = true; - writing = true; - sync(); - writing = false; - editor.focus(); - }); - on(input, "input", () => { - if (!writing) sync(); - }); - on(input, "change", () => { - if (!writing) sync(); - }); - on(popup, "click", (event) => { - const day = event.target.closest("[data-date]"); - if (day && !day.disabled) { - write(day.dataset.date, true); - close(true); - } - const month = event.target.closest("[data-month]"); - if (month) { - view.setDate(1); - view.setMonth(view.getMonth() + Number(month.dataset.month)); - draw(); - popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); - } - }); - on(popup, "keydown", (event) => { - if (event.key === "Escape") { - event.preventDefault(); - event.stopPropagation(); - close(true); - return; - } - const button = event.target.closest("[data-date]"); - if (!button) return; - const delta = { - ArrowLeft: -1, - ArrowRight: 1, - ArrowUp: -7, - ArrowDown: 7 - }[event.key]; - if (delta !== void 0 || [ - "Home", - "End", - "PageUp", - "PageDown" - ].includes(event.key)) { - event.preventDefault(); - const next = parse(button.dataset.date); - if (delta !== void 0) next.setDate(next.getDate() + delta); - else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); - else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); - else { - const day = next.getDate(); - next.setDate(1); - next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); - const end = new Date(next); - end.setMonth(end.getMonth() + 1); - end.setDate(0); - next.setDate(Math.min(day, end.getDate())); - } - if (enabledDay(format(next))) { - view = next; - activeDay = format(next); - draw(); - popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); - } - } - }); - on(editor, "keydown", (event) => { - if (date && event.altKey && event.key === "ArrowDown") { - event.preventDefault(); - show(); - } - }); - on(input.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(input.ownerDocument.activeElement)) close(); - })); - on(input.ownerDocument, "reset", (event) => { - if (event.target === input.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - touched = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(input.ownerDocument.defaultView, "resize", () => { - if (open) place(opener, popup); - }); - const observer = new MutationObserver(sync); - observer.observe(input, { - attributes: true, - attributeFilter: [ - "value", - "min", - "max", - "step", - "disabled", - "readonly", - "required", - "form", - "aria-invalid", - "aria-describedby", - "aria-label", - "aria-labelledby" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { - attributes: true, - attributeFilter: ["disabled"] - }); - const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); - if (!Object.hasOwn(input, "value")) { - Object.defineProperty(input, "value", { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(value) { - descriptor.set.call(this, value); - if (!writing) sync(); - } - }); - restore.push(() => delete input.value); - } - if (!Object.hasOwn(input, "focus")) { - Object.defineProperty(input, "focus", { - configurable: true, - value: (options) => editor.focus(options) - }); - restore.push(() => delete input.focus); - } - sync(); - const api = { - sync, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restore.forEach((fn) => fn()); - shell.remove(); - for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); - instances.delete(input); - } - }; - instances.set(input, api); - return api; -} -//#endregion -//#region packages/ui/src/internal/choice.js -var mounted = /* @__PURE__ */ new WeakMap(); -var sequence = 0; -function mountChoice(select) { - if (mounted.has(select)) return mounted.get(select); - const abort = new AbortController(), restorers = []; - const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { - ...options, - signal: abort.signal - }); - const multiple = select.multiple; - let id; - do - id = `j3w1-choice-${++sequence}`; - while (select.ownerDocument.getElementById(`${id}-control`)); - const shell = make(select, "span", { - class: "j3w1-choice", - "data-choice-for": select.id - }); - const list = make(select, "span", { - class: "j3w1-choice-list", - id: `${id}-list`, - role: "listbox" - }); - const control = multiple ? list : make(select, "button", { - class: "j3w1-choice-trigger", - type: "button", - role: "combobox", - "aria-haspopup": "listbox", - "aria-controls": list.id, - "aria-expanded": "false" - }); - const value = make(select, "span", { class: "j3w1-choice-value" }); - const message = make(select, "span", { - class: "j3w1-choice-error", - id: `${id}-error`, - role: "status", - hidden: "" - }); - if (multiple) { - list.setAttribute("aria-multiselectable", "true"); - list.tabIndex = 0; - } else { - control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); - list.hidden = true; - list.setAttribute("popover", "manual"); - shell.append(control); - } - shell.append(list, message); - select.after(shell); - const saved = new Map([ - "hidden", - "aria-hidden", - "tabindex" - ].map((name) => [name, select.getAttribute(name)])); - select.hidden = true; - select.setAttribute("aria-hidden", "true"); - select.tabIndex = -1; - let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; - const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; - const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); - const labels = [...select.labels ?? []]; - control.id = `${id}-control`; - for (const label of labels) { - const previous = label.getAttribute("for"); - label.htmlFor = control.id; - restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); - } - const labelText = () => controlLabelText(labels); - const close = () => { - if (multiple) return; - if (list.matches(":popover-open")) list.hidePopover(); - list.hidden = true; - open = false; - control.setAttribute("aria-expanded", "false"); - control.removeAttribute("aria-activedescendant"); - }; - const focus = (options) => { - if (!select.matches(":disabled")) control.focus(options); - }; - const mark = (index) => { - active = index; - items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); - if (items[active] && (multiple || open)) { - control.setAttribute("aria-activedescendant", items[active].node.id); - if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); - } else control.removeAttribute("aria-activedescendant"); - }; - const sync = () => { - if (updating || abort.signal.aborted) return; - const off = select.matches(":disabled"); - control.setAttribute("aria-disabled", String(off)); - control.tabIndex = off ? -1 : 0; - if (!multiple) control.disabled = off; - if (off) close(); - const labelled = select.getAttribute("aria-labelledby"); - if (labelled) { - control.setAttribute("aria-labelledby", labelled); - control.removeAttribute("aria-label"); - } else { - control.removeAttribute("aria-labelledby"); - control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); - } - if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); - control.setAttribute("aria-required", String(select.required)); - const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; - control.setAttribute("aria-invalid", String(bad)); - message.hidden = !bad; - message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; - const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); - if (described) control.setAttribute("aria-describedby", described); - else control.removeAttribute("aria-describedby"); - items.forEach(({ option, node }) => { - node.setAttribute("aria-selected", String(option.selected)); - node.setAttribute("aria-disabled", String(disabled(option))); - node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); - }); - value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; - if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); - }; - const hook = (object, name, changed) => { - if (Object.getOwnPropertyDescriptor(object, name)) return; - let proto = Object.getPrototypeOf(object), descriptor; - while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); - if (!descriptor?.set || !descriptor.get) return; - Object.defineProperty(object, name, { - configurable: true, - get() { - return descriptor.get.call(this); - }, - set(next) { - descriptor.set.call(this, next); - changed(); - } - }); - restorers.push(() => delete object[name]); - }; - const watched = /* @__PURE__ */ new WeakSet(); - const rebuild = () => { - const current = items[active]?.option; - list.replaceChildren(); - items = []; - for (const child of select.children) { - let parent = list; - if (child.tagName === "OPTGROUP") { - parent = make(select, "span", { - role: "group", - "aria-label": child.label, - class: "j3w1-choice-group" - }); - parent.append(make(select, "span", { - class: "j3w1-choice-group-label", - "aria-hidden": "true" - }, child.label)); - list.append(parent); - } - for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { - const node = make(select, "span", { - class: "j3w1-choice-option", - role: "option", - id: `${id}-option-${items.length}`, - "data-choice-value": option.value - }); - node.append(make(select, "span", { - class: "j3w1-choice-check", - "aria-hidden": "true" - }, "✓"), make(select, "span", {}, option.label)); - parent.append(node); - items.push({ - option, - node - }); - if (!watched.has(option)) { - hook(option, "selected", sync); - watched.add(option); - } - } - } - active = items.findIndex((item) => item.option === current); - sync(); - }; - const show = () => { - if (multiple || select.matches(":disabled")) return; - sync(); - list.hidden = false; - open = true; - control.setAttribute("aria-expanded", "true"); - list.style.width = `${control.getBoundingClientRect().width}px`; - if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); - place(control, list); - mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); - }; - const commit = (index, range = false) => { - const item = items[index]; - if (!item || disabled(item.option) || select.matches(":disabled")) return; - updating = true; - if (multiple) { - if (range && anchor >= 0) items.forEach((entry, i) => { - if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); - }); - else { - item.option.selected = !item.option.selected; - anchor = index; - } - } else select.selectedIndex = [...select.options].indexOf(item.option); - updating = false; - invalid = true; - sync(); - if (!multiple) close(); - nativeInput(select); - nativeInput(select, "change"); - if (control.isConnected) focus(); - }; - on(control, "keydown", (event) => { - if (select.matches(":disabled")) return; - const indices = usable(); - if (event.key === "Escape") { - if (open) { - event.preventDefault(); - event.stopPropagation(); - close(); - } - return; - } - if (event.key === "Tab") { - close(); - return; - } - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { - event.preventDefault(); - updating = true; - const all = indices.every((i) => items[i].option.selected); - indices.forEach((i) => { - items[i].option.selected = !all; - }); - updating = false; - sync(); - nativeInput(select); - nativeInput(select, "change"); - return; - } - if (["Enter", " "].includes(event.key)) { - event.preventDefault(); - if (!multiple && !open) show(); - else commit(active, event.shiftKey); - return; - } - if (event.altKey && event.key === "ArrowUp") { - event.preventDefault(); - close(); - return; - } - if ([ - "ArrowDown", - "ArrowUp", - "Home", - "End" - ].includes(event.key)) { - event.preventDefault(); - const wasOpen = open; - if (!multiple && !open) show(); - if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; - const position = indices.indexOf(active); - const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; - mark(next); - if (multiple && event.shiftKey) commit(next, true); - return; - } - if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { - event.preventDefault(); - if (!multiple && !open) show(); - const now = Date.now(); - buffer = now - typedAt > 700 ? event.key : buffer + event.key; - typedAt = now; - const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; - const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; - const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); - if (next !== void 0) mark(next); - } - }); - if (!multiple) on(control, "click", (event) => { - event.preventDefault(); - focus(); - open ? close() : show(); - }); - on(list, "pointerdown", (event) => event.preventDefault()); - on(list, "click", (event) => { - const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); - if (index < 0) return; - event.preventDefault(); - mark(index); - commit(index, event.shiftKey); - }); - on(select, "input", sync); - on(select, "change", sync); - on(select, "invalid", (event) => { - event.preventDefault(); - invalid = true; - sync(); - focus(); - }); - on(select.ownerDocument, "reset", (event) => { - if (event.target === select.form) queueMicrotask(() => { - if (!event.defaultPrevented) { - invalid = false; - close(); - sync(); - } - }); - }, { capture: true }); - on(select.ownerDocument, "pointerdown", (event) => { - if (!shell.contains(event.target)) close(); - }); - on(shell, "focusout", () => queueMicrotask(() => { - if (!shell.contains(select.ownerDocument.activeElement)) close(); - })); - on(select.ownerDocument.defaultView, "resize", () => { - if (open) place(control, list); - }); - on(select.ownerDocument, "scroll", (event) => { - if (open && !list.contains(event.target)) place(control, list); - }, { capture: true }); - for (const label of labels) on(label, "click", (event) => { - if (!shell.contains(event.target)) { - event.preventDefault(); - focus(); - } - }); - const observer = new MutationObserver(rebuild); - observer.observe(select, { - subtree: true, - childList: true, - characterData: true, - attributes: true, - attributeFilter: [ - "disabled", - "required", - "label", - "value", - "selected", - "hidden", - "aria-label", - "aria-labelledby", - "aria-describedby", - "aria-invalid" - ] - }); - const fieldsets = new MutationObserver(sync); - for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { - attributes: true, - attributeFilter: ["disabled"] - }); - hook(select, "value", sync); - hook(select, "selectedIndex", sync); - if (!Object.getOwnPropertyDescriptor(select, "focus")) { - Object.defineProperty(select, "focus", { - configurable: true, - value: focus - }); - restorers.push(() => delete select.focus); - } - rebuild(); - const api = { - sync, - focus, - show, - hide: close, - get open() { - return open; - }, - destroy() { - if (abort.signal.aborted) return; - close(); - abort.abort(); - observer.disconnect(); - fieldsets.disconnect(); - restorers.forEach((restore) => restore()); - shell.remove(); - for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); - mounted.delete(select); - } - }; - mounted.set(select, api); - return api; -} -function enhanceControls(root) { - const choices = /* @__PURE__ */ new Map(); - root.setAttribute("data-j3w1-controls", ""); - const refresh = () => { - for (const [select, api] of choices) if (!root.contains(select)) { - api.destroy(); - choices.delete(select); - } - for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { - let owner = select.parentElement; - while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; - if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); - } - }; - const observer = new MutationObserver(refresh); - observer.observe(root, { - childList: true, - subtree: true - }); - refresh(); - return { - refresh, - destroy() { - observer.disconnect(); - choices.forEach((api) => api.destroy()); - choices.clear(); - root.removeAttribute("data-j3w1-controls"); - } - }; -} -//#endregion -export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/wizard/runtime/chunks/choice-DqwWT5pJ.js b/packages/ui/dist/copy/wizard/runtime/chunks/choice-DqwWT5pJ.js new file mode 100644 index 000000000..a20d3e3f6 --- /dev/null +++ b/packages/ui/dist/copy/wizard/runtime/chunks/choice-DqwWT5pJ.js @@ -0,0 +1,935 @@ +// packages/ui/src/internal/dom.js +var all = (root, selector) => [...root.querySelectorAll(selector)]; +var enabled = (node) => !node.matches(":disabled") && node.getAttribute("aria-disabled") !== "true"; +var visible = (node) => !node.closest("[hidden]"); +function controlLabelText(labels) { + const text = (node) => { + if (node.nodeType === 3) return node.textContent; + if (node.nodeType !== 1) return ""; + if (node.matches("input,select,textarea,.j3w1-choice,.j3w1-temporal,[aria-hidden=\"true\"],[hidden]")) return ""; + const style = node.ownerDocument.defaultView.getComputedStyle(node); + if (style.display === "none" || style.visibility === "hidden") return ""; + return [...node.childNodes].map(text).join(""); + }; + return labels.map((label) => [...label.childNodes].map(text).join("").trim()).join(" "); +} +function announce(root, message) { + let status = root.querySelector("[data-j3w1-status]"); + if (!status) { + status = root.ownerDocument.createElement("p"); + status.dataset.j3w1Status = ""; + status.className = "j3w1-visually-hidden"; + status.setAttribute("role", "status"); + root.append(status); + } + status.textContent = message; +} +function identify(root, node, suffix) { + if (node && !node.id) node.id = `${root.id}-${suffix}`; + return node?.id; +} +function nativeInput(input, type = "input") { + input.dispatchEvent(new Event(type, { bubbles: true })); +} +function keyIndex({ key, index, length, next = "ArrowDown", previous = "ArrowUp", wrap = true }) { + if (key === "Home") return 0; + if (key === "End") return length - 1; + const target = index + (key === next ? 1 : key === previous ? -1 : 0); + return wrap ? (target + length) % length : Math.max(0, Math.min(length - 1, target)); +} +function rove(items, index, focus = true) { + if (!items.length) return null; + const next = items[(index + items.length) % items.length]; + items.forEach((item) => { + item.tabIndex = item === next ? 0 : -1; + }); + if (focus) next.focus(); + return next; +} +function make(root, tag, attrs = {}, text) { + const node = root.ownerDocument.createElement(tag); + for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, String(value)); + if (text !== void 0) node.textContent = String(text); + return node; +} +function makeIcon(root, d, attrs = {}) { + const ns = "http://www.w3.org/2000/svg"; + const svg = root.ownerDocument.createElementNS(ns, "svg"); + for (const [key, value] of Object.entries({ + viewBox: "0 0 16 16", + width: "16", + height: "16", + "aria-hidden": "true", + focusable: "false", + ...attrs + })) svg.setAttribute(key, String(value)); + const path = root.ownerDocument.createElementNS(ns, "path"); + for (const [key, value] of Object.entries({ + d, + fill: "none", + stroke: "currentColor", + "stroke-width": "1.5" + })) path.setAttribute(key, value); + svg.append(path); + return svg; +} +function place(trigger, popup) { + const r = trigger.getBoundingClientRect(), p = popup.getBoundingClientRect(); + const doc = trigger.ownerDocument.documentElement; + const left = Math.max(8, Math.min(r.left, doc.clientWidth - p.width - 8)); + const top = r.bottom + p.height + 8 > doc.clientHeight ? Math.max(8, r.top - p.height) : r.bottom; + Object.assign(popup.style, { + position: "fixed", + insetInlineStart: "auto", + insetInlineEnd: "auto", + left: `${left}px`, + top: `${top}px`, + maxHeight: `${Math.max(120, doc.clientHeight - top - 8)}px`, + overflowY: "auto" + }); +} +// packages/ui/src/internal/temporal.js +var instances = /* @__PURE__ */ new WeakMap(); +var sequence$1 = 0; +function mountTemporal(input) { + if (instances.has(input)) return instances.get(input); + const abort = new AbortController(), restore = [], date = input.getAttribute("type") === "date", nativeTemporal = input.type === input.getAttribute("type"); + const numeric = (value) => { + if (date) { + if (!/^\d{4,}-\d{2}-\d{2}$/.test(value)) return NaN; + const stamp = Date.parse(`${value}T00:00:00Z`); + return Number.isFinite(stamp) && new Date(stamp).toISOString().slice(0, 10) === value ? stamp / 864e5 : NaN; + } + const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/.exec(value); + if (!match || Number(match[1]) > 23 || Number(match[2]) > 59 || Number(match[3] ?? 0) > 59) return NaN; + return Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3] ?? 0) + Number(`0.${match[4] ?? 0}`); + }; + const stepSize = () => Number(input.step) > 0 ? Number(input.step) : date ? 1 : 60; + const constraint = (value) => { + const number = numeric(value), min = numeric(input.min), max = numeric(input.max); + if (!Number.isFinite(number)) return value ? "Enter a valid value." : input.required ? "Choose a value." : ""; + if (!date && min > max) { + if (number < min && number > max) return "Choose a time within the allowed range."; + } else if (number < min || number > max) return "Choose a value within the allowed range."; + const base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0; + if (input.step !== "any" && Math.abs((number - base) / stepSize() - Math.round((number - base) / stepSize())) > 1e-7) return "Choose a value matching the allowed step."; + return ""; + }; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + let id; + do + id = `j3w1-temporal-${++sequence$1}`; + while (input.ownerDocument.getElementById(`${id}-input`)); + const shell = make(input, "span", { class: "j3w1-temporal" }), row = make(input, "span", { class: "j3w1-temporal-row" }); + const editor = make(input, "input", { + id: `${id}-input`, + type: "text", + class: "j3w1-temporal-input", + autocomplete: "off", + placeholder: date ? "YYYY-MM-DD" : "HH:MM", + inputmode: "text" + }); + const message = make(input, "span", { + id: `${id}-error`, + class: "j3w1-choice-error", + role: "status", + hidden: "" + }); + const popup = make(input, "span", { + class: "j3w1-calendar", + role: "dialog", + "aria-modal": "false", + "aria-label": "Choose date", + popover: "manual", + hidden: "" + }); + const opener = make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": date ? "Open calendar" : "Increase time" + }, date ? "▦" : "+"); + row.append(editor, opener); + const decrease = date ? null : make(input, "button", { + type: "button", + class: "j3w1-temporal-action", + "aria-label": "Decrease time" + }, "−"); + if (decrease) row.append(decrease); + shell.append(row, message); + if (date) shell.append(popup); + input.after(shell); + const labels = [...input.labels ?? []]; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = editor.id; + restore.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const attributes = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, input.getAttribute(name)])); + input.hidden = true; + input.setAttribute("aria-hidden", "true"); + input.tabIndex = -1; + let touched = false, writing = false, open = false, view = /* @__PURE__ */ new Date(), activeDay = null, fallbackError = ""; + const format = (value) => `${String(value.getFullYear()).padStart(4, "0")}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`; + const parse = (value) => /* @__PURE__ */ new Date(`${value}T12:00:00`); + const labelText = () => controlLabelText(labels); + const close = (focus = false) => { + if (popup.matches(":popover-open")) popup.hidePopover(); + popup.hidden = true; + open = false; + opener.setAttribute("aria-expanded", "false"); + if (focus) editor.focus(); + }; + const sync = () => { + if (abort.signal.aborted) return; + if (!writing) editor.value = input.value; + editor.disabled = input.matches(":disabled"); + editor.readOnly = input.readOnly; + editor.required = input.required; + if (input.hasAttribute("form")) editor.setAttribute("form", input.getAttribute("form")); + else editor.removeAttribute("form"); + opener.disabled = editor.disabled || editor.readOnly || !date && input.step === "any"; + if (decrease) decrease.disabled = opener.disabled; + if (opener.disabled) close(); + const labelled = input.getAttribute("aria-labelledby"); + if (labelled) { + editor.setAttribute("aria-labelledby", labelled); + editor.removeAttribute("aria-label"); + } else { + editor.removeAttribute("aria-labelledby"); + editor.setAttribute("aria-label", input.getAttribute("aria-label") || labelText() || (date ? "Date" : "Time")); + } + if (!nativeTemporal) { + if (input.validationMessage === fallbackError) input.setCustomValidity(""); + fallbackError = constraint(editor.value); + if (!input.validationMessage) input.setCustomValidity(fallbackError); + } + const malformed = Boolean(editor.value && !Number.isFinite(numeric(editor.value))); + editor.setCustomValidity(malformed ? `Enter a valid ${date ? "date in YYYY-MM-DD format" : "time in HH:MM or HH:MM:SS format"}.` : input.validationMessage); + const invalid = touched && !editor.validity.valid || input.getAttribute("aria-invalid") === "true"; + editor.setAttribute("aria-invalid", String(invalid)); + message.hidden = !invalid; + message.textContent = invalid ? editor.validationMessage || "Enter a valid value." : ""; + const described = [input.getAttribute("aria-describedby"), date ? "Use YYYY-MM-DD format." : "Use HH:MM or HH:MM:SS format."]; + if (!shell.querySelector(".j3w1-temporal-hint")) shell.append(make(input, "span", { + class: "j3w1-temporal-hint", + id: `${id}-hint` + }, described[1])); + editor.setAttribute("aria-describedby", [ + described[0], + `${id}-hint`, + invalid ? message.id : "" + ].filter(Boolean).join(" ")); + }; + const write = (value, change = false) => { + writing = true; + editor.value = value; + input.value = Number.isFinite(numeric(value)) ? value : ""; + nativeInput(input); + if (change) { + touched = true; + nativeInput(input, "change"); + } + sync(); + writing = false; + }; + const enabledDay = (value) => !constraint(value); + const draw = () => { + popup.replaceChildren(); + const heading = make(input, "span", { class: "j3w1-calendar-heading" }), previous = make(input, "button", { + type: "button", + "data-month": "-1", + "aria-label": "Previous month" + }, "←"), next = make(input, "button", { + type: "button", + "data-month": "1", + "aria-label": "Next month" + }, "→"); + const title = make(input, "strong", { id: `${id}-month` }, view.toLocaleDateString(void 0, { + month: "long", + year: "numeric" + })); + heading.append(previous, title, next); + popup.append(heading); + const grid = make(input, "span", { + role: "grid", + "aria-labelledby": title.id, + class: "j3w1-calendar-grid" + }); + const header = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + for (const day of [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ]) header.append(make(input, "span", { role: "columnheader" }, day)); + grid.append(header); + const first = new Date(view); + first.setDate(1); + const last = new Date(first); + last.setMonth(last.getMonth() + 1); + last.setDate(0); + let week; + for (let index = 0; index < first.getDay() + last.getDate(); index++) { + if (index % 7 === 0) { + week = make(input, "span", { + role: "row", + class: "j3w1-calendar-week" + }); + grid.append(week); + } + const cell = make(input, "span", { role: "gridcell" }); + week.append(cell); + const day = index - first.getDay() + 1; + if (day < 1) continue; + const current = new Date(first); + current.setDate(day); + const value = format(current), button = make(input, "button", { + type: "button", + "data-date": value, + tabindex: value === activeDay ? "0" : "-1", + "aria-label": current.toLocaleDateString(void 0, { dateStyle: "full" }), + "aria-pressed": String(value === input.value) + }, day); + button.disabled = !enabledDay(value); + cell.append(button); + } + popup.append(grid); + if (!popup.querySelector("button[data-date][tabindex=\"0\"]:not(:disabled)")) { + const first = popup.querySelector("button[data-date]:not(:disabled)"); + if (first) { + first.tabIndex = 0; + activeDay = first.dataset.date; + } + } + if (open) place(opener, popup); + }; + const show = () => { + if (opener.disabled) return; + const selected = parse(input.value); + view = Number.isNaN(selected.valueOf()) ? /* @__PURE__ */ new Date() : selected; + activeDay = format(view); + open = true; + popup.hidden = false; + opener.setAttribute("aria-expanded", "true"); + draw(); + if (typeof popup.showPopover === "function") popup.showPopover(); + place(opener, popup); + popup.querySelector("[data-date][tabindex=\"0\"]")?.focus(); + }; + if (date) { + opener.setAttribute("aria-haspopup", "dialog"); + opener.setAttribute("aria-expanded", "false"); + on(opener, "click", () => open ? close(true) : show()); + } else { + const step = (amount) => { + if (nativeTemporal) { + amount > 0 ? input.stepUp() : input.stepDown(); + write(input.value, true); + } else { + const min = numeric(input.min), current = numeric(input.value), base = Number.isFinite(min) ? min : Number.isFinite(numeric(input.defaultValue)) ? numeric(input.defaultValue) : 0, size = stepSize(), position = ((Number.isFinite(current) ? current : base) - base) / size; + const value = base + (amount > 0 ? Math.floor(position) + 1 : Math.ceil(position) - 1) * size; + if (value >= 0 && value < 86400) { + const hours = String(Math.floor(value / 3600)).padStart(2, "0"), minutes = String(Math.floor(value % 3600 / 60)).padStart(2, "0"), seconds = String(Math.floor(value % 60)).padStart(2, "0"), fraction = Math.round(value % 1 * 1e3); + const text = `${hours}:${minutes}${value % 60 ? `:${seconds}${fraction ? `.${String(fraction).padStart(3, "0")}` : ""}` : ""}`; + if (!constraint(text)) write(text, true); + } + } + editor.focus(); + }; + on(opener, "click", () => step(1)); + on(decrease, "click", () => step(-1)); + } + on(editor, "input", (event) => { + event.stopPropagation(); + write(editor.value); + }); + on(editor, "change", (event) => { + event.stopPropagation(); + write(editor.value, true); + }); + for (const control of [editor, input]) on(control, "invalid", (event) => { + event.preventDefault(); + touched = true; + writing = true; + sync(); + writing = false; + editor.focus(); + }); + on(input, "input", () => { + if (!writing) sync(); + }); + on(input, "change", () => { + if (!writing) sync(); + }); + on(popup, "click", (event) => { + const day = event.target.closest("[data-date]"); + if (day && !day.disabled) { + write(day.dataset.date, true); + close(true); + } + const month = event.target.closest("[data-month]"); + if (month) { + view.setDate(1); + view.setMonth(view.getMonth() + Number(month.dataset.month)); + draw(); + popup.querySelector(`[data-month="${month.dataset.month}"]`)?.focus(); + } + }); + on(popup, "keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + close(true); + return; + } + const button = event.target.closest("[data-date]"); + if (!button) return; + const delta = { + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -7, + ArrowDown: 7 + }[event.key]; + if (delta !== void 0 || [ + "Home", + "End", + "PageUp", + "PageDown" + ].includes(event.key)) { + event.preventDefault(); + const next = parse(button.dataset.date); + if (delta !== void 0) next.setDate(next.getDate() + delta); + else if (event.key === "Home") next.setDate(next.getDate() - next.getDay()); + else if (event.key === "End") next.setDate(next.getDate() + 6 - next.getDay()); + else { + const day = next.getDate(); + next.setDate(1); + next.setMonth(next.getMonth() + (event.key === "PageDown" ? 1 : -1)); + const end = new Date(next); + end.setMonth(end.getMonth() + 1); + end.setDate(0); + next.setDate(Math.min(day, end.getDate())); + } + if (enabledDay(format(next))) { + view = next; + activeDay = format(next); + draw(); + popup.querySelector(`[data-date="${activeDay}"]`)?.focus(); + } + } + }); + on(editor, "keydown", (event) => { + if (date && event.altKey && event.key === "ArrowDown") { + event.preventDefault(); + show(); + } + }); + on(input.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(input.ownerDocument.activeElement)) close(); + })); + on(input.ownerDocument, "reset", (event) => { + if (event.target === input.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + touched = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(input.ownerDocument.defaultView, "resize", () => { + if (open) place(opener, popup); + }); + const observer = new MutationObserver(sync); + observer.observe(input, { + attributes: true, + attributeFilter: [ + "value", + "min", + "max", + "step", + "disabled", + "readonly", + "required", + "form", + "aria-invalid", + "aria-describedby", + "aria-label", + "aria-labelledby" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let node = input.parentElement; node; node = node.parentElement) if (node.tagName === "FIELDSET") fieldsets.observe(node, { + attributes: true, + attributeFilter: ["disabled"] + }); + const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(input), "value"); + if (!Object.hasOwn(input, "value")) { + Object.defineProperty(input, "value", { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(value) { + descriptor.set.call(this, value); + if (!writing) sync(); + } + }); + restore.push(() => delete input.value); + } + if (!Object.hasOwn(input, "focus")) { + Object.defineProperty(input, "focus", { + configurable: true, + value: (options) => editor.focus(options) + }); + restore.push(() => delete input.focus); + } + sync(); + const api = { + sync, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restore.forEach((fn) => fn()); + shell.remove(); + for (const [name, value] of attributes) value === null ? input.removeAttribute(name) : input.setAttribute(name, value); + instances.delete(input); + } + }; + instances.set(input, api); + return api; +} +// packages/ui/src/internal/choice.js +var mounted = /* @__PURE__ */ new WeakMap(); +var sequence = 0; +function mountChoice(select) { + if (mounted.has(select)) return mounted.get(select); + const abort = new AbortController(), restorers = []; + const on = (node, type, fn, options = {}) => node?.addEventListener(type, fn, { + ...options, + signal: abort.signal + }); + const multiple = select.multiple; + let id; + do + id = `j3w1-choice-${++sequence}`; + while (select.ownerDocument.getElementById(`${id}-control`)); + const shell = make(select, "span", { + class: "j3w1-choice", + "data-choice-for": select.id + }); + const list = make(select, "span", { + class: "j3w1-choice-list", + id: `${id}-list`, + role: "listbox" + }); + const control = multiple ? list : make(select, "button", { + class: "j3w1-choice-trigger", + type: "button", + role: "combobox", + "aria-haspopup": "listbox", + "aria-controls": list.id, + "aria-expanded": "false" + }); + const value = make(select, "span", { class: "j3w1-choice-value" }); + const message = make(select, "span", { + class: "j3w1-choice-error", + id: `${id}-error`, + role: "status", + hidden: "" + }); + if (multiple) { + list.setAttribute("aria-multiselectable", "true"); + list.tabIndex = 0; + } else { + control.append(value, makeIcon(select, "M3.5 6 8 10.5 12.5 6", { class: "j3w1-choice-chevron" })); + list.hidden = true; + list.setAttribute("popover", "manual"); + shell.append(control); + } + shell.append(list, message); + select.after(shell); + const saved = new Map([ + "hidden", + "aria-hidden", + "tabindex" + ].map((name) => [name, select.getAttribute(name)])); + select.hidden = true; + select.setAttribute("aria-hidden", "true"); + select.tabIndex = -1; + let items = [], active = -1, anchor = -1, open = false, updating = false, invalid = false, buffer = "", typedAt = 0; + const disabled = (option) => option.disabled || option.parentElement?.matches("optgroup:disabled, optgroup[hidden]") || option.hidden; + const usable = () => items.map((item, index) => disabled(item.option) ? -1 : index).filter((index) => index >= 0); + const labels = [...select.labels ?? []]; + control.id = `${id}-control`; + for (const label of labels) { + const previous = label.getAttribute("for"); + label.htmlFor = control.id; + restorers.push(() => previous === null ? label.removeAttribute("for") : label.setAttribute("for", previous)); + } + const labelText = () => controlLabelText(labels); + const close = () => { + if (multiple) return; + if (list.matches(":popover-open")) list.hidePopover(); + list.hidden = true; + open = false; + control.setAttribute("aria-expanded", "false"); + control.removeAttribute("aria-activedescendant"); + }; + const focus = (options) => { + if (!select.matches(":disabled")) control.focus(options); + }; + const mark = (index) => { + active = index; + items.forEach((item, i) => item.node.toggleAttribute("data-active", i === active)); + if (items[active] && (multiple || open)) { + control.setAttribute("aria-activedescendant", items[active].node.id); + if (open || select.ownerDocument.activeElement === control) items[active].node.scrollIntoView({ block: "nearest" }); + } else control.removeAttribute("aria-activedescendant"); + }; + const sync = () => { + if (updating || abort.signal.aborted) return; + const off = select.matches(":disabled"); + control.setAttribute("aria-disabled", String(off)); + control.tabIndex = off ? -1 : 0; + if (!multiple) control.disabled = off; + if (off) close(); + const labelled = select.getAttribute("aria-labelledby"); + if (labelled) { + control.setAttribute("aria-labelledby", labelled); + control.removeAttribute("aria-label"); + } else { + control.removeAttribute("aria-labelledby"); + control.setAttribute("aria-label", select.getAttribute("aria-label") || labelText() || select.name || "Choose an option"); + } + if (!multiple) list.setAttribute("aria-label", control.getAttribute("aria-label") || labelText() || "Options"); + control.setAttribute("aria-required", String(select.required)); + const bad = invalid && !select.validity.valid || select.getAttribute("aria-invalid") === "true"; + control.setAttribute("aria-invalid", String(bad)); + message.hidden = !bad; + message.textContent = bad ? select.validationMessage || "Choose a valid option." : ""; + const described = [select.getAttribute("aria-describedby"), bad ? message.id : ""].filter(Boolean).join(" "); + if (described) control.setAttribute("aria-describedby", described); + else control.removeAttribute("aria-describedby"); + items.forEach(({ option, node }) => { + node.setAttribute("aria-selected", String(option.selected)); + node.setAttribute("aria-disabled", String(disabled(option))); + node.hidden = option.hidden || Boolean(option.parentElement?.matches("optgroup[hidden]")); + }); + value.textContent = [...select.selectedOptions].map((option) => option.label).join(", ") || "Choose an option"; + if (!items[active] || disabled(items[active].option)) mark(usable()[0] ?? -1); + }; + const hook = (object, name, changed) => { + if (Object.getOwnPropertyDescriptor(object, name)) return; + let proto = Object.getPrototypeOf(object), descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, name))) proto = Object.getPrototypeOf(proto); + if (!descriptor?.set || !descriptor.get) return; + Object.defineProperty(object, name, { + configurable: true, + get() { + return descriptor.get.call(this); + }, + set(next) { + descriptor.set.call(this, next); + changed(); + } + }); + restorers.push(() => delete object[name]); + }; + const watched = /* @__PURE__ */ new WeakSet(); + const rebuild = () => { + const current = items[active]?.option; + list.replaceChildren(); + items = []; + for (const child of select.children) { + let parent = list; + if (child.tagName === "OPTGROUP") { + parent = make(select, "span", { + role: "group", + "aria-label": child.label, + class: "j3w1-choice-group" + }); + parent.append(make(select, "span", { + class: "j3w1-choice-group-label", + "aria-hidden": "true" + }, child.label)); + list.append(parent); + } + for (const option of child.tagName === "OPTION" ? [child] : child.querySelectorAll("option")) { + const node = make(select, "span", { + class: "j3w1-choice-option", + role: "option", + id: `${id}-option-${items.length}`, + "data-choice-value": option.value + }); + node.append(make(select, "span", { + class: "j3w1-choice-check", + "aria-hidden": "true" + }, "✓"), make(select, "span", {}, option.label)); + parent.append(node); + items.push({ + option, + node + }); + if (!watched.has(option)) { + hook(option, "selected", sync); + watched.add(option); + } + } + } + active = items.findIndex((item) => item.option === current); + sync(); + }; + const show = () => { + if (multiple || select.matches(":disabled")) return; + sync(); + list.hidden = false; + open = true; + control.setAttribute("aria-expanded", "true"); + list.style.width = `${control.getBoundingClientRect().width}px`; + if (typeof list.showPopover === "function" && !list.matches(":popover-open")) list.showPopover(); + place(control, list); + mark(items.findIndex((item) => item.option.selected && !disabled(item.option)) >= 0 ? items.findIndex((item) => item.option.selected && !disabled(item.option)) : usable()[0] ?? -1); + }; + const commit = (index, range = false) => { + const item = items[index]; + if (!item || disabled(item.option) || select.matches(":disabled")) return; + updating = true; + if (multiple) { + if (range && anchor >= 0) items.forEach((entry, i) => { + if (!disabled(entry.option)) entry.option.selected = i >= Math.min(anchor, index) && i <= Math.max(anchor, index); + }); + else { + item.option.selected = !item.option.selected; + anchor = index; + } + } else select.selectedIndex = [...select.options].indexOf(item.option); + updating = false; + invalid = true; + sync(); + if (!multiple) close(); + nativeInput(select); + nativeInput(select, "change"); + if (control.isConnected) focus(); + }; + on(control, "keydown", (event) => { + if (select.matches(":disabled")) return; + const indices = usable(); + if (event.key === "Escape") { + if (open) { + event.preventDefault(); + event.stopPropagation(); + close(); + } + return; + } + if (event.key === "Tab") { + close(); + return; + } + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a" && multiple) { + event.preventDefault(); + updating = true; + const all = indices.every((i) => items[i].option.selected); + indices.forEach((i) => { + items[i].option.selected = !all; + }); + updating = false; + sync(); + nativeInput(select); + nativeInput(select, "change"); + return; + } + if (["Enter", " "].includes(event.key)) { + event.preventDefault(); + if (!multiple && !open) show(); + else commit(active, event.shiftKey); + return; + } + if (event.altKey && event.key === "ArrowUp") { + event.preventDefault(); + close(); + return; + } + if ([ + "ArrowDown", + "ArrowUp", + "Home", + "End" + ].includes(event.key)) { + event.preventDefault(); + const wasOpen = open; + if (!multiple && !open) show(); + if (!indices.length || event.altKey || !multiple && !wasOpen && !["Home", "End"].includes(event.key)) return; + const position = indices.indexOf(active); + const next = event.key === "Home" ? indices[0] : event.key === "End" ? indices.at(-1) : indices[Math.max(0, Math.min(indices.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)))]; + mark(next); + if (multiple && event.shiftKey) commit(next, true); + return; + } + if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) { + event.preventDefault(); + if (!multiple && !open) show(); + const now = Date.now(); + buffer = now - typedAt > 700 ? event.key : buffer + event.key; + typedAt = now; + const query = [...buffer].every((char) => char === buffer[0]) ? buffer[0] : buffer; + const start = query.length === 1 ? indices.indexOf(active) + 1 : 0; + const next = [...indices.slice(start), ...indices.slice(0, start)].find((i) => items[i].option.label.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())); + if (next !== void 0) mark(next); + } + }); + if (!multiple) on(control, "click", (event) => { + event.preventDefault(); + focus(); + open ? close() : show(); + }); + on(list, "pointerdown", (event) => event.preventDefault()); + on(list, "click", (event) => { + const index = items.findIndex((item) => item.node === event.target.closest("[role=\"option\"]")); + if (index < 0) return; + event.preventDefault(); + mark(index); + commit(index, event.shiftKey); + }); + on(select, "input", sync); + on(select, "change", sync); + on(select, "invalid", (event) => { + event.preventDefault(); + invalid = true; + sync(); + focus(); + }); + on(select.ownerDocument, "reset", (event) => { + if (event.target === select.form) queueMicrotask(() => { + if (!event.defaultPrevented) { + invalid = false; + close(); + sync(); + } + }); + }, { capture: true }); + on(select.ownerDocument, "pointerdown", (event) => { + if (!shell.contains(event.target)) close(); + }); + on(shell, "focusout", () => queueMicrotask(() => { + if (!shell.contains(select.ownerDocument.activeElement)) close(); + })); + on(select.ownerDocument.defaultView, "resize", () => { + if (open) place(control, list); + }); + on(select.ownerDocument, "scroll", (event) => { + if (open && !list.contains(event.target)) place(control, list); + }, { capture: true }); + for (const label of labels) on(label, "click", (event) => { + if (!shell.contains(event.target)) { + event.preventDefault(); + focus(); + } + }); + const observer = new MutationObserver(rebuild); + observer.observe(select, { + subtree: true, + childList: true, + characterData: true, + attributes: true, + attributeFilter: [ + "disabled", + "required", + "label", + "value", + "selected", + "hidden", + "aria-label", + "aria-labelledby", + "aria-describedby", + "aria-invalid" + ] + }); + const fieldsets = new MutationObserver(sync); + for (let parent = select.parentElement; parent; parent = parent.parentElement) if (parent.tagName === "FIELDSET") fieldsets.observe(parent, { + attributes: true, + attributeFilter: ["disabled"] + }); + hook(select, "value", sync); + hook(select, "selectedIndex", sync); + if (!Object.getOwnPropertyDescriptor(select, "focus")) { + Object.defineProperty(select, "focus", { + configurable: true, + value: focus + }); + restorers.push(() => delete select.focus); + } + rebuild(); + const api = { + sync, + focus, + show, + hide: close, + get open() { + return open; + }, + destroy() { + if (abort.signal.aborted) return; + close(); + abort.abort(); + observer.disconnect(); + fieldsets.disconnect(); + restorers.forEach((restore) => restore()); + shell.remove(); + for (const [name, value] of saved) value === null ? select.removeAttribute(name) : select.setAttribute(name, value); + mounted.delete(select); + } + }; + mounted.set(select, api); + return api; +} +function enhanceControls(root) { + const choices = /* @__PURE__ */ new Map(); + root.setAttribute("data-j3w1-controls", ""); + const refresh = () => { + for (const [select, api] of choices) if (!root.contains(select)) { + api.destroy(); + choices.delete(select); + } + for (const select of root.querySelectorAll("select,input[type=\"date\"],input[type=\"time\"]")) { + let owner = select.parentElement; + while (owner && !owner.localName.startsWith("j3w1-")) owner = owner.parentElement; + if (!select.closest("j3w1-select,j3w1-date-picker,j3w1-time-picker") && (!owner || owner === root) && !choices.has(select)) choices.set(select, select.tagName === "SELECT" ? mountChoice(select) : mountTemporal(select)); + } + }; + const observer = new MutationObserver(refresh); + observer.observe(root, { + childList: true, + subtree: true + }); + refresh(); + return { + refresh, + destroy() { + observer.disconnect(); + choices.forEach((api) => api.destroy()); + choices.clear(); + root.removeAttribute("data-j3w1-controls"); + } + }; +} +export { announce as a, keyIndex as c, place as d, rove as f, all as i, make as l, mountChoice as n, enabled as o, visible as p, mountTemporal as r, identify as s, enhanceControls as t, nativeInput as u }; diff --git a/packages/ui/dist/copy/wizard/runtime/chunks/element-DcrNU9Wh.js b/packages/ui/dist/copy/wizard/runtime/chunks/element-DcrNU9Wh.js new file mode 100644 index 000000000..86fb43da9 --- /dev/null +++ b/packages/ui/dist/copy/wizard/runtime/chunks/element-DcrNU9Wh.js @@ -0,0 +1,231 @@ +import { t as enhanceControls } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/internal/element.js +var HTMLElementBase = globalThis.HTMLElement ?? class {}; +var nextInstance = 0; +var J3w1Element = class extends HTMLElementBase { + static observedAttributes = [ + "disabled", + "required", + "readonly", + "name", + "value", + "checked", + "loading", + "tone" + ]; + #abort; + #cleanup; + #queued = false; + #disabledChildren = /* @__PURE__ */ new Map(); + #retained = /* @__PURE__ */ new Map(); + #controllerState; + #initializedControls = /* @__PURE__ */ new WeakSet(); + get control() { + return this.querySelector("input,select,textarea,button,progress"); + } + get controls() { + return [...this.querySelectorAll("input,select,textarea,button")]; + } + get value() { + if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; + return this.control?.value ?? this.getAttribute("value") ?? ""; + } + set value(value) { + if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.checked = input.value === String(value); + }); + else if (this.control) this.control.value = String(value ?? ""); + else this.setAttribute("value", String(value ?? "")); + this._api?.valueChanged?.(); + } + get checked() { + return this.control?.checked ?? this.hasAttribute("checked"); + } + set checked(value) { + if (this.control && "checked" in this.control) this.control.checked = Boolean(value); + else this.toggleAttribute("checked", Boolean(value)); + } + get disabled() { + return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); + } + set disabled(value) { + this.toggleAttribute("disabled", Boolean(value)); + } + get required() { + return this.control?.required ?? this.hasAttribute("required"); + } + set required(value) { + this.toggleAttribute("required", Boolean(value)); + } + get readOnly() { + return this.control?.readOnly ?? this.hasAttribute("readonly"); + } + set readOnly(value) { + this.toggleAttribute("readonly", Boolean(value)); + } + get name() { + return this.control?.name ?? this.getAttribute("name") ?? ""; + } + set name(value) { + this.setAttribute("name", String(value)); + } + get form() { + return this.control?.form ?? null; + } + checkValidity() { + return this.controls.every((control) => !control.checkValidity || control.checkValidity()); + } + reportValidity() { + for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; + return true; + } + focus(options) { + (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); + } + connectedCallback() { + if (this.#queued) return; + this.#queued = true; + queueMicrotask(() => { + this.#queued = false; + if (this.isConnected) this.refresh(); + }); + } + disconnectedCallback() { + if (this._api) { + this.#controllerState = this._api.snapshot?.(); + for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); + } + this.#abort?.abort(); + this.#cleanup?.(); + this.#cleanup = void 0; + this._api = void 0; + } + attributeChangedCallback(name, oldValue, value) { + if (oldValue === value) return; + this.applyAttribute(name, value); + this._api?.attributeChanged?.(name, oldValue, value); + } + applyAttribute(name, value) { + const control = this.control; + if (!control) return; + if (name === "disabled") { + for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); + for (const node of this.controls) if (value !== null) { + if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); + node.disabled = true; + } else if (this.#disabledChildren.has(node)) { + node.disabled = this.#disabledChildren.get(node); + this.#disabledChildren.delete(node); + } + } else if (["required", "readonly"].includes(name)) { + if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); + } else if (name === "checked" && "checked" in control) { + control.defaultChecked = value !== null; + control.checked = value !== null; + } else if (name === "value") { + if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { + input.defaultChecked = input.value === value; + input.checked = input.value === value; + }); + else { + if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; + control.value = value ?? ""; + } + this._api?.valueChanged?.(); + } else if (name === "name") { + if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { + input.name = value ?? ""; + }); + else control.name = value ?? ""; + } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); + else if (name === "tone" && control.matches("button")) for (const tone of [ + "secondary", + "tertiary", + "destructive" + ]) control.classList.toggle(`button-${tone}`, value === tone); + } + emit(type, detail = {}) { + return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + refresh() { + this.disconnectedCallback(); + this.#abort = new AbortController(); + const signal = this.#abort.signal; + this.dataset.j3w1Component = this.constructor.componentId; + this.dataset.j3w1Version = this.constructor.version; + if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; + const control = this.control; + for (const name of this.constructor.observedAttributes) { + if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; + if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); + } + if (control) this.#initializedControls.add(control); + this.addEventListener("click", (event) => { + const control = event.target.closest("button,a,input"); + if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }, { + capture: true, + signal + }); + this.addEventListener("change", (event) => { + if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { + value: event.target.value, + checked: event.target.checked, + name: event.target.name + }); + }, { signal }); + const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { + ...options, + signal + }); + const connection = this.constructor.connect?.(this, { + on, + signal + }); + const cleanup = typeof connection === "function" ? connection : connection?.cleanup; + const controls = enhanceControls(this); + this.#cleanup = () => { + controls.destroy(); + cleanup?.(); + }; + this._api = typeof connection === "object" ? connection : void 0; + if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); + this.#controllerState = void 0; + for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; + this.#retained.clear(); + for (const name of /* @__PURE__ */ new Set([ + "value", + "checked", + "disabled", + "required", + "readOnly", + "name", + ...this.constructor.upgradeProperties ?? [] + ])) if (Object.hasOwn(this, name)) { + const value = this[name]; + delete this[name]; + this[name] = value; + } + } +}; +function registerElement(name, Constructor, registry = globalThis.customElements) { + if (!registry) throw new Error("Register components in a browser with Custom Elements support."); + const current = registry.get(name); + const sameBuild = current && [ + "componentId", + "version", + "implementationId" + ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); + if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); + if (!current) registry.define(name, Constructor); + return current ?? Constructor; +} +export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/wizard/runtime/chunks/element-Dovcr9Ky.js b/packages/ui/dist/copy/wizard/runtime/chunks/element-Dovcr9Ky.js deleted file mode 100644 index aa7a67cb4..000000000 --- a/packages/ui/dist/copy/wizard/runtime/chunks/element-Dovcr9Ky.js +++ /dev/null @@ -1,232 +0,0 @@ -import { t as enhanceControls } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/internal/element.js -var HTMLElementBase = globalThis.HTMLElement ?? class {}; -var nextInstance = 0; -var J3w1Element = class extends HTMLElementBase { - static observedAttributes = [ - "disabled", - "required", - "readonly", - "name", - "value", - "checked", - "loading", - "tone" - ]; - #abort; - #cleanup; - #queued = false; - #disabledChildren = /* @__PURE__ */ new Map(); - #retained = /* @__PURE__ */ new Map(); - #controllerState; - #initializedControls = /* @__PURE__ */ new WeakSet(); - get control() { - return this.querySelector("input,select,textarea,button,progress"); - } - get controls() { - return [...this.querySelectorAll("input,select,textarea,button")]; - } - get value() { - if (this.control?.type === "radio") return this.querySelector("input[type=\"radio\"]:checked")?.value ?? ""; - return this.control?.value ?? this.getAttribute("value") ?? ""; - } - set value(value) { - if (this.control?.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.checked = input.value === String(value); - }); - else if (this.control) this.control.value = String(value ?? ""); - else this.setAttribute("value", String(value ?? "")); - this._api?.valueChanged?.(); - } - get checked() { - return this.control?.checked ?? this.hasAttribute("checked"); - } - set checked(value) { - if (this.control && "checked" in this.control) this.control.checked = Boolean(value); - else this.toggleAttribute("checked", Boolean(value)); - } - get disabled() { - return this.control?.matches(":disabled") ?? this.hasAttribute("disabled"); - } - set disabled(value) { - this.toggleAttribute("disabled", Boolean(value)); - } - get required() { - return this.control?.required ?? this.hasAttribute("required"); - } - set required(value) { - this.toggleAttribute("required", Boolean(value)); - } - get readOnly() { - return this.control?.readOnly ?? this.hasAttribute("readonly"); - } - set readOnly(value) { - this.toggleAttribute("readonly", Boolean(value)); - } - get name() { - return this.control?.name ?? this.getAttribute("name") ?? ""; - } - set name(value) { - this.setAttribute("name", String(value)); - } - get form() { - return this.control?.form ?? null; - } - checkValidity() { - return this.controls.every((control) => !control.checkValidity || control.checkValidity()); - } - reportValidity() { - for (const control of this.controls) if (control.reportValidity && !control.reportValidity()) return false; - return true; - } - focus(options) { - (this.querySelector("input:not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),a[href],summary,[tabindex=\"0\"]") ?? this.control)?.focus(options); - } - connectedCallback() { - if (this.#queued) return; - this.#queued = true; - queueMicrotask(() => { - this.#queued = false; - if (this.isConnected) this.refresh(); - }); - } - disconnectedCallback() { - if (this._api) { - this.#controllerState = this._api.snapshot?.(); - for (const name of this.constructor.upgradeProperties ?? []) if (name in this._api) this.#retained.set(name, this._api[name]); - } - this.#abort?.abort(); - this.#cleanup?.(); - this.#cleanup = void 0; - this._api = void 0; - } - attributeChangedCallback(name, oldValue, value) { - if (oldValue === value) return; - this.applyAttribute(name, value); - this._api?.attributeChanged?.(name, oldValue, value); - } - applyAttribute(name, value) { - const control = this.control; - if (!control) return; - if (name === "disabled") { - for (const node of this.#disabledChildren.keys()) if (!this.contains(node)) this.#disabledChildren.delete(node); - for (const node of this.controls) if (value !== null) { - if (!this.#disabledChildren.has(node)) this.#disabledChildren.set(node, node.disabled); - node.disabled = true; - } else if (this.#disabledChildren.has(node)) { - node.disabled = this.#disabledChildren.get(node); - this.#disabledChildren.delete(node); - } - } else if (["required", "readonly"].includes(name)) { - if (control.matches("input,select,textarea")) control.toggleAttribute(name, value !== null); - } else if (name === "checked" && "checked" in control) { - control.defaultChecked = value !== null; - control.checked = value !== null; - } else if (name === "value") { - if (control.type === "radio") this.querySelectorAll("input[type=\"radio\"]").forEach((input) => { - input.defaultChecked = input.value === value; - input.checked = input.value === value; - }); - else { - if ("defaultValue" in control && control.type !== "file") control.defaultValue = value ?? ""; - control.value = value ?? ""; - } - this._api?.valueChanged?.(); - } else if (name === "name") { - if (["radio", "checkbox"].includes(control.type)) this.querySelectorAll(`input[type="${control.type}"]`).forEach((input) => { - input.name = value ?? ""; - }); - else control.name = value ?? ""; - } else if (name === "loading") control.setAttribute("aria-busy", String(value !== null)); - else if (name === "tone" && control.matches("button")) for (const tone of [ - "secondary", - "tertiary", - "destructive" - ]) control.classList.toggle(`button-${tone}`, value === tone); - } - emit(type, detail = {}) { - return this.dispatchEvent(new CustomEvent(`j3w1-${type}`, { - detail, - bubbles: true, - composed: true, - cancelable: true - })); - } - refresh() { - this.disconnectedCallback(); - this.#abort = new AbortController(); - const signal = this.#abort.signal; - this.dataset.j3w1Component = this.constructor.componentId; - this.dataset.j3w1Version = this.constructor.version; - if (!this.id) this.id = `j3w1-instance-${++nextInstance}`; - const control = this.control; - for (const name of this.constructor.observedAttributes) { - if (["value", "checked"].includes(name) && control && this.#initializedControls.has(control)) continue; - if (this.hasAttribute(name)) this.applyAttribute(name, this.getAttribute(name)); - } - if (control) this.#initializedControls.add(control); - this.addEventListener("click", (event) => { - const control = event.target.closest("button,a,input"); - if (control && (control.getAttribute("aria-disabled") === "true" || this.hasAttribute("loading"))) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }, { - capture: true, - signal - }); - this.addEventListener("change", (event) => { - if (event.target.closest("[data-j3w1-component]") === this) this.emit("change", { - value: event.target.value, - checked: event.target.checked, - name: event.target.name - }); - }, { signal }); - const on = (target, type, fn, options = {}) => target?.addEventListener(type, fn, { - ...options, - signal - }); - const connection = this.constructor.connect?.(this, { - on, - signal - }); - const cleanup = typeof connection === "function" ? connection : connection?.cleanup; - const controls = enhanceControls(this); - this.#cleanup = () => { - controls.destroy(); - cleanup?.(); - }; - this._api = typeof connection === "object" ? connection : void 0; - if (this.#controllerState !== void 0) this._api?.restore?.(this.#controllerState); - this.#controllerState = void 0; - for (const [name, value] of this.#retained) if (!Object.hasOwn(this, name) && !Object.is(this[name], value)) this[name] = value; - this.#retained.clear(); - for (const name of /* @__PURE__ */ new Set([ - "value", - "checked", - "disabled", - "required", - "readOnly", - "name", - ...this.constructor.upgradeProperties ?? [] - ])) if (Object.hasOwn(this, name)) { - const value = this[name]; - delete this[name]; - this[name] = value; - } - } -}; -function registerElement(name, Constructor, registry = globalThis.customElements) { - if (!registry) throw new Error("Register components in a browser with Custom Elements support."); - const current = registry.get(name); - const sameBuild = current && [ - "componentId", - "version", - "implementationId" - ].every((key) => typeof Constructor[key] === "string" && Constructor[key].length > 0 && current[key] === Constructor[key]); - if (current && current !== Constructor && !sameBuild) throw new Error(`A different implementation already owns ${name}`); - if (!current) registry.define(name, Constructor); - return current ?? Constructor; -} -//#endregion -export { registerElement as n, J3w1Element as t }; diff --git a/packages/ui/dist/copy/wizard/runtime/chunks/forms-CE_hP1hg.js b/packages/ui/dist/copy/wizard/runtime/chunks/forms-C3u5121t.js similarity index 96% rename from packages/ui/dist/copy/wizard/runtime/chunks/forms-CE_hP1hg.js rename to packages/ui/dist/copy/wizard/runtime/chunks/forms-C3u5121t.js index 6ad3b48f5..7eaab7c98 100644 --- a/packages/ui/dist/copy/wizard/runtime/chunks/forms-CE_hP1hg.js +++ b/packages/ui/dist/copy/wizard/runtime/chunks/forms-C3u5121t.js @@ -1,5 +1,5 @@ -import { i as all, l as make, o as enabled } from "./choice-B7mo5Eq3.js"; -//#region packages/ui/src/behaviors/forms.js +import { i as all, l as make, o as enabled } from "./choice-DqwWT5pJ.js"; +// packages/ui/src/behaviors/forms.js function wizard(root, { on }) { const panels = all(root, ".wizard-panel"), steps = all(root, ".wizard-step-button"), backButton = root.querySelector(".wizard-back"), nextButton = root.querySelector(".wizard-next"); if (!panels.length || panels.length !== steps.length) throw new Error("A wizard requires one complete panel for each step button"); @@ -119,5 +119,4 @@ function formComposition(root, { on }) { if (root.querySelector("[data-start=\"review\"]")) showReview(false); return {}; } -//#endregion export { wizard as n, formComposition as t }; diff --git a/packages/ui/dist/copy/wizard/runtime/components/wizard.js b/packages/ui/dist/copy/wizard/runtime/components/wizard.js index 852097735..775e64794 100644 --- a/packages/ui/dist/copy/wizard/runtime/components/wizard.js +++ b/packages/ui/dist/copy/wizard/runtime/components/wizard.js @@ -1,10 +1,10 @@ -import { t as J3w1Element } from "../chunks/element-Dovcr9Ky.js"; -import { n as wizard } from "../chunks/forms-CE_hP1hg.js"; -//#region .cache/ui-build/entries/components/wizard.js +import { t as J3w1Element } from "../chunks/element-DcrNU9Wh.js"; +import { n as wizard } from "../chunks/forms-C3u5121t.js"; +// .cache/ui-build/entries/components/wizard.js var J3w1Wizard = class extends J3w1Element { static componentId = "wizard"; static version = "4.0.0"; - static implementationId = "sha256-RPzZPFnWZYndDTCn4JxgWR8s+kGEDCPgKxzzaesMZdk="; + static implementationId = "sha256-wTcu4zP0i8kvSlxtwGFtrYx/9baiKjAH6nC33cNC3v8="; static connect = wizard; static upgradeProperties = [ "disabled", @@ -32,5 +32,4 @@ var J3w1Wizard = class extends J3w1Element { }); } }; -//#endregion export { J3w1Wizard }; diff --git a/packages/ui/dist/copy/wizard/runtime/register/wizard.js b/packages/ui/dist/copy/wizard/runtime/register/wizard.js index df8a879a1..075e5d568 100644 --- a/packages/ui/dist/copy/wizard/runtime/register/wizard.js +++ b/packages/ui/dist/copy/wizard/runtime/register/wizard.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Wizard } from "../components/wizard.js"; -//#region .cache/ui-build/entries/register/wizard.js +// .cache/ui-build/entries/register/wizard.js var element = registerElement("j3w1-wizard", J3w1Wizard); -//#endregion export { element }; diff --git a/packages/ui/dist/enhance/choice.js b/packages/ui/dist/enhance/choice.js index 7b9f12b2c..d4bf3dd29 100644 --- a/packages/ui/dist/enhance/choice.js +++ b/packages/ui/dist/enhance/choice.js @@ -1 +1 @@ -export { t as enhanceControls } from "../chunks/choice-B7mo5Eq3.js"; +export { t as enhanceControls } from "../chunks/choice-DqwWT5pJ.js"; diff --git a/packages/ui/dist/enhance/form-builder.js b/packages/ui/dist/enhance/form-builder.js index 200a14f5a..4a4cc7c49 100644 --- a/packages/ui/dist/enhance/form-builder.js +++ b/packages/ui/dist/enhance/form-builder.js @@ -1 +1 @@ -export { t as mountBuilder } from "../chunks/form-builder-BRIaVVFY.js"; +export { t as mountBuilder } from "../chunks/form-builder-DbZUZMo1.js"; diff --git a/packages/ui/dist/enhance/form-workflow.js b/packages/ui/dist/enhance/form-workflow.js index 07eb153fe..79e83ebf0 100644 --- a/packages/ui/dist/enhance/form-workflow.js +++ b/packages/ui/dist/enhance/form-workflow.js @@ -1 +1 @@ -export { t as mountWorkflow } from "../chunks/form-workflow-BKRLylvq.js"; +export { t as mountWorkflow } from "../chunks/form-workflow-B183Y5gc.js"; diff --git a/packages/ui/dist/index.js b/packages/ui/dist/index.js index 97696cd1d..82d3055a1 100644 --- a/packages/ui/dist/index.js +++ b/packages/ui/dist/index.js @@ -21,7 +21,7 @@ import { J3w1TimePicker } from "./components/time-picker.js"; import { J3w1FileInput } from "./components/file-input.js"; import { J3w1Repeater } from "./components/repeater.js"; import { J3w1Wizard } from "./components/wizard.js"; -import { t as J3w1FormBuilder } from "./chunks/form-builder-BvWZCBPR.js"; +import { t as J3w1FormBuilder } from "./chunks/form-builder-CkeTBQe-.js"; import { J3w1Tabs } from "./components/tabs.js"; import { J3w1Breadcrumbs } from "./components/breadcrumbs.js"; import { J3w1Pagination } from "./components/pagination.js"; diff --git a/packages/ui/dist/manifest.json b/packages/ui/dist/manifest.json index bd798ce19..e42e65599 100644 --- a/packages/ui/dist/manifest.json +++ b/packages/ui/dist/manifest.json @@ -518,18 +518,18 @@ "copy": { "directory": "copy/button/", "files": { - "runtime/register/button.js": "sha256-HvNFbu03EVUxXcYT4la11XNeC522dyJdNi3USEnMuL0=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/button.js": "sha256-csyoBHNGYp8/JTgXnOjZuGEFG9u6KytBLHY3MtJdxcs=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/button.js": "sha256-xBHeJlZwrTjeg7JzsVRbjiBe9MekpRJR+0ALoHB3Lhk=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/button.js": "sha256-AUGeIp5H3ziJjknDX7a+AGZ3l56vccuGARDQe1NEJ5o=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-3CHgfHOT+xBve253iRY/PvSWDiyrTR4uMxiCy2jC7OQ=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-kLEcMMhF4Tv+byKkImEgGIqqR+QYh6uOOCz/mg5hkPs=", "index.html": "sha256-O3BLqD/CIvh8B0MWobTc8e8XgjfKiYym6Ekh+jLDiGU=", "README.md": "sha256-q0HhyjwcljqPHR5pUVYK1uw9OCz+qKStetrXmYwvBR0=", - "manifest.json": "sha256-W2vgMYD1GCX3nA8jySc1GPBP93dPoIbu2ppqti6N/Bg=" + "manifest.json": "sha256-vW6Doqi2/lmML0KV+cfq8S3WWL8tJ5SOwdkafLEblDU=" } } }, @@ -891,18 +891,18 @@ "copy": { "directory": "copy/icon-button/", "files": { - "runtime/register/icon-button.js": "sha256-L08i/ocUFPtCTSEsrOlL0bHzGs89QBIj/rBasLRJtLo=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/icon-button.js": "sha256-vf1OEF/kOZCVO/ZtfRZNwQ9lE6RvDSCB/Ra1MK1iFVI=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/icon-button.js": "sha256-Mw32ruY/czDFoyg4pH+EqKXUI/YsRFK4ZwwZotabWs4=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/icon-button.js": "sha256-wswYMnAITXd1cUjEIoNhQQb/Omx26cZEilDQ3SywHDk=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-il6XyTxz1/FNWyp/lAP2zeoQKrY/yezCXO7+BWH4SLU=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Zd5z+/mavK2J24Rl+RQLGhMT+nTLwoOf3bAJevwrz7s=", "index.html": "sha256-KThGCU4j/urAhf3dBSdh3EZIfGyU5sUJD2tDkaUj7pU=", "README.md": "sha256-kfL9rqvRiTy+cXrhgmDnHSmrAvPR1uA5rKGMQPP1UIM=", - "manifest.json": "sha256-2xkFEJzgTFx4dNWThkOC1wrAi8DrqXB1N6TFj7VJ0Qs=" + "manifest.json": "sha256-vFMZfyom6J5jKe5u37mHDrjUk7IocatZaJ0FZFF9eco=" } } }, @@ -1230,18 +1230,18 @@ "copy": { "directory": "copy/link/", "files": { - "runtime/register/link.js": "sha256-U3xi1OrLtFVeA80lAjw3YJnW9ACONTzsce1B9Xf844w=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/link.js": "sha256-bR26HhC67XHGaYwnQAazew60MupqT70YRgV+2U5TNxA=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/link.js": "sha256-jwozmacnZdRn6lvmvgeeUqRw+j+qRnBfRC2vt9UgGbk=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/link.js": "sha256-k1UsDjyh7ID9N1QSWtczvBEYdMfs4xsybrRLTGFzYGQ=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-uxvP2GjnvVzGp+CHY0D7UPQ+7qXQiFem1DAnSc7jCyY=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-I9IW2mf0VnX5LtCoHDI29AJHW7PXUxnRReiAbsbd094=", "index.html": "sha256-3ig1s+AQmoMBXGTeRFYZnQvO+kBuTk2gzuIniK+u1Rc=", "README.md": "sha256-x8NFY5DSM/rYjOcAeTMFjFuNeI2xoG8yxyGfTnk8/wk=", - "manifest.json": "sha256-oTafIE+IAViI0oHnUU2yc+nCoe21J1ceIY04WDL80cE=" + "manifest.json": "sha256-YmGKhqI/aDiKuv7KQV05qIOTAOfLCF/v+TkfJI/zcCA=" } } }, @@ -1769,18 +1769,18 @@ "copy": { "directory": "copy/button-group/", "files": { - "runtime/register/button-group.js": "sha256-n7o1qzR7ijgCLKarzz6j0E+PWPYtlemBEaNgIZwu2R4=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/button-group.js": "sha256-aYOeTtqsQuXqHLxIh17+FGxd0WuETY31YqUOFh32A4A=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/button-group.js": "sha256-CFMDZp4J0G3eNpyzz9h6e411fRQd4qCFeWFwo78IXAM=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/button-group.js": "sha256-03J38xNN25EiiWRaSOx/ndOebdEU8ay5ANw68TOo1sc=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-0HQ2nfSUmtlZV8Bwsob1wBnVODkxbeI16OqeME3hc2M=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-4NLobHuAfZnWUQDNQ3ENH9ucyjTTUTD6gk0XV7SHGng=", "index.html": "sha256-9LPOwo7I6LrlkFlPCMTTeH5e5/ncW+/6Qpk6VBEoVnI=", "README.md": "sha256-lxk9uEo0CDVb02dn3zqLATkEEbC7gk0mkkX9yRpWCC8=", - "manifest.json": "sha256-OV9ljuCQx8r8eDk+U9iS1DT7aSUPtvKcipUl75sYW1s=" + "manifest.json": "sha256-Oj60S70C3/4Fcn4PirxNRaULxvlKmJFSmjikxcLT+6s=" } } }, @@ -2237,18 +2237,18 @@ "copy": { "directory": "copy/segmented-control/", "files": { - "runtime/register/segmented-control.js": "sha256-n6tsq/njNAYhqF4fvBMTvNQc+KRA4dsIBCmrUsrTA+U=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/segmented-control.js": "sha256-8hAeFwje9ZkB0c6k2tQrV2hjw4TCznTY3w0tOFD/egQ=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/segmented-control.js": "sha256-OeqnvpiM0P88F9H4q+eT555nEkKiMwf8ieOzeMnawzg=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/segmented-control.js": "sha256-hTlWptpOLy1sPlY00bm/exJfRnlx3Sxna0aJaoS41Ok=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-+okbI0q5jMbA3Dv/3pcbgQ3LJeXS73lSYOUnG9ki9UE=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-/y5XrVYeuiIc2/pZ/wdJWuadUAGF48in7tED7hWQGYI=", "index.html": "sha256-1knSx3CNDwcXYtsJuGWn26xP1MjuCfSw99/6QgvIyBM=", "README.md": "sha256-lEaJfO3PJMUKPPqSK45yRRL6euErAHItarIyeoshEI4=", - "manifest.json": "sha256-ZQNn2MS86VKyf2NasdJBqcyJh6uVyTThUKh/SeDPG28=" + "manifest.json": "sha256-DgIl3kuSiWylQj+tMiQsBsG1qqSbA/cWM/yb/ce86/E=" } } }, @@ -2626,18 +2626,18 @@ "copy": { "directory": "copy/field/", "files": { - "runtime/register/field.js": "sha256-zLQtzqVvRVMiR9nicBMgkx8zeeoejrZolk/zDj6Q1Q4=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/field.js": "sha256-ummTNywyrj12MoNMHDD5qiPFCif8xG24RwdhXXF7LnU=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/field.js": "sha256-idnG0SIbXzZPGP1U3H9jFyhEUzotK2gRMKB/6ZZQQLo=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/field.js": "sha256-7DL5f/G9uaZueJ05MP0+CoD5fXGcX5gl7rU5qy2lAZg=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-NdGAWLleLWawKN47P/spgrR/kdjbB/c8l7xBXcLxIoI=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-M+Faw3Q4PMYCRgzzkpyGYO6m3Sefbyj3JZ3/wdlvGPU=", "index.html": "sha256-9Oc3cWMsPHjFbRxnXV+vSB2DCa377qyZ5xvP9m6Gn3s=", "README.md": "sha256-AzjdGpWnzYlGi9+vtMZD2GQ180dH8au7cLFaahlKJZw=", - "manifest.json": "sha256-LpNdRh0ag+40WP0osnDPicBeZVJCfyJFNw5hveNtVGE=" + "manifest.json": "sha256-7nP3BG+2sl/bArEWKUNRs85KiQVcdaxY8HLZ9HhQT0A=" } } }, @@ -3177,18 +3177,18 @@ "copy": { "directory": "copy/text-field/", "files": { - "runtime/register/text-field.js": "sha256-gmqyzVDUD/VCnOF5nDRA0n1F4I7q7lE02AdZeBCFrUk=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/text-field.js": "sha256-4c47ee0iFW2YWW+dVR1PBSJMwOOa5rmKhJSalXzm+Zo=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/text-field.js": "sha256-MdEo5+b/G/mM5hz7fcSDyO//Htiapsit78fIYEhm59k=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/text-field.js": "sha256-qPB+cDkHzpm0/dIb3MLq2aw8aYuTw8eeiXDYfuaVwwE=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-e3OAwau9F97LYarFVXWbKIfnS2R8w0n/O47hHa1tjco=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-R8UtNVXLOQSMMT+NPAGht8BHx8b1yIjvTii2pQlPs8k=", "index.html": "sha256-ss2KbC0xuZHLx75wVTAJ1qD3+NlEUPn/1dOG4DGQX1g=", "README.md": "sha256-U5UskFkuRc314VHTU09nhnEvLqV//5UXlnD2tS0RftI=", - "manifest.json": "sha256-hcXV2Vi1DhJRQohjSviBXp1aXkPz9EviFqirXPNm87o=" + "manifest.json": "sha256-j9nXR2jD4nunrrFDVZngRnTMw7V+jHlKqlWwFdYVed8=" } } }, @@ -3684,18 +3684,18 @@ "copy": { "directory": "copy/textarea/", "files": { - "runtime/register/textarea.js": "sha256-OGjZrk++zzTI91HXv7chKm86kRb5xICVcoOOdMidF2g=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/textarea.js": "sha256-pi3Oj4itdBVYU/EaRSZ64BqAEsBdeUH4LCG2kwSUKfw=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/textarea.js": "sha256-kKiC3PacJzn+IIdz6JEkzMEOawMA3/ge/FCAnqsmWPM=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/textarea.js": "sha256-/Z89vI8KLV9ojTcxZPRnV0C0nGRVDX3vFp0LRy/BR4M=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-VB3HAgE+H7HB6tMee0dbFbD3l1YmgFtsLiCzLuvGZzs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-FrTRU04fY9wZ6rThXepEiAOHAf/WPEcefiPDsYvSLsM=", "index.html": "sha256-O3FxWIEbLMDDY8Ok2G+bKB16TiTYtpgkOAaF9Q1gYYo=", "README.md": "sha256-F6nGVVbKhFVOmZH/GiI2JV5yeoVGMJCFzjcytVdyGrs=", - "manifest.json": "sha256-DyaG2k7o6BlcPa+H2TJnjk2tqWxwmqrMOE5RDZJkxBw=" + "manifest.json": "sha256-nrds2Ehx9pEgrAOTQ/KJcaXUXxUJE8UgzxMg6MKgQXg=" } } }, @@ -4305,18 +4305,18 @@ "copy": { "directory": "copy/select/", "files": { - "runtime/register/select.js": "sha256-TN7apnaEDR69Eobpnesx4c3Yr2iU33xNGj/q9i+nFtw=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/select.js": "sha256-QSO5F4fiwtnnIHZ9/a9n62yVZRlGUIofNkw2oXYIzGY=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/select.js": "sha256-a/ebYoMxXf0lulroJxRYiTUDtJLmr23xOp4f3nhwepc=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/select.js": "sha256-5I3s1W7GlcelP7ffSDNZXafcFZmzILO7gFZrwhZh9Ps=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-F6DQsNcbPkf+LkJ534A3xYbg7WBsLszKxMa9zap0wK0=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-1rMGJynWvvm/FG3mKaD7Cc+QHA+zhkGFyc7tL4Ul37Q=", "index.html": "sha256-qUab8G+JxhJZ5W/BmBgl23HVr/q8JLQmyIi5tTTX4JU=", "README.md": "sha256-MrNAdB126mt16m2mdh0VynM3ujESd5+tjBkbyYHVpQw=", - "manifest.json": "sha256-jvw2jUqqMRw42q/rCfMJ1eS6/dOU257qg8Qtc/DI5OE=" + "manifest.json": "sha256-XEWUAUggOHYqBYRi90mxbOkUw6nSflvv1BkdttlrVn4=" } } }, @@ -4814,18 +4814,18 @@ "copy": { "directory": "copy/checkbox/", "files": { - "runtime/register/checkbox.js": "sha256-QlNtS75LVxO+OKEWX5af518TWUVOwH5nVS8bKid/E+Y=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/checkbox.js": "sha256-M4ffC3UZvNt1LaayV7iUubw0dG33RiqLTYcb05lK3N4=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/checkbox.js": "sha256-4FXUPwf4ix3wwVjE+fGDDGgVp+oXhoxuin7qwnMqYYY=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/checkbox.js": "sha256-wYmcBKQmc0+hPiMjdLSxHFSci1qcX0h7DyRtiOtB62o=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-UbNMFdu+HW8ujyQExwYwdN9wZDBkKRrgWyLfrTITwec=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-D5pZAWuWF8+C90nVIZnSREv1i0fk6q9L+6SEdvU1Okk=", "index.html": "sha256-PXIpEMN5ECxZXpbQG1pVzJUZwEslHvYulHsJlfHplz0=", "README.md": "sha256-WEnN989sIQKKMpAjmYvjRbS2hGIBqYi+IEj9c/xhVFs=", - "manifest.json": "sha256-JI8rTznen/f8jQhHRPNS9DIrpFO2Xy3aEhj534QeX6k=" + "manifest.json": "sha256-/ZoXbFntvWo05tyf1uBWkVt4qrFshxfjHstu3kJCQ7g=" } } }, @@ -5250,18 +5250,18 @@ "copy": { "directory": "copy/radio-group/", "files": { - "runtime/register/radio-group.js": "sha256-ewlJRFup1XukqJJNHbI7o4+IBxMHYc4zRErGTSTTCOE=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/radio-group.js": "sha256-2H9k0HsCH7vOePvpZIurg4X8R/tWx69+wbMsKbawdJQ=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/radio-group.js": "sha256-zr8E48f84xnrzU/bENHN+06GlwRTImWeLSXQJM6JSYk=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/radio-group.js": "sha256-pTf7n/I+GJNCcHKGvEvK9JeW+47LLqnSqA0IMQvcFvg=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-YV0K4E9IvTApjrBK9vEmi8LtX8q3bUSlq810ysD4Kpk=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-6HA7gvr2JUQeKZ5jWPcVyfSw5t4FmaqlAA/+mhuSJjc=", "index.html": "sha256-JXkdz3Ty4ygZ8c9K7ftH4J8rbquZw4UXpB47/g2uw1g=", "README.md": "sha256-L+Z3W5VfP83lnvB20pwCI2E1gQ/vKF4Yvd/mDw4diyE=", - "manifest.json": "sha256-aJ2H5pEQm+ytgIHM353fOv8WWj0EZ/2w5JjFn10rJKc=" + "manifest.json": "sha256-Wa2jIhHL4dSop5RhJtxZbHhzpRCaXnVrnms6lj3RAJU=" } } }, @@ -5663,18 +5663,18 @@ "copy": { "directory": "copy/switch/", "files": { - "runtime/register/switch.js": "sha256-6l7gxY7bHWXI4K8WMdikGfg6Itnf2Uy8hSbsvn+XCYM=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/switch.js": "sha256-sdfSvJlKylAeDbhRKPMRUZ+piEOzKs1aV52BDvjOV/o=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/switch.js": "sha256-DuUxpd3L4nKgHvyJPWJ+2TZBOWxcTy0MOtxrbgEWF/I=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/switch.js": "sha256-CVbrKOXLXh5ZRJ7UrRkrE+VgZ8zGcaD6GE1mYPPDdio=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-tykFKJCLb7EnJ9BYN4wbrmCaS+Vo3TtOvIKoQ1viFfI=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-bja8BqOYebPhAJ/84m7EUQysf7pqQJ3wMJ10wj4YBz4=", "index.html": "sha256-IF4S7//PahcEGINA+vv8hBV9DUViABqK+t6Eyfb0B1Y=", "README.md": "sha256-9Yw9PXXsjkMqCnWGR6UbhauQtlI0q6dR39YdGBbG71A=", - "manifest.json": "sha256-9qe7Own3wU6ScYVQZPEqWsp3h4rbch44RxcFcHbty7Y=" + "manifest.json": "sha256-KNKjAzlF7Lo8fV7B+NujiUUl+g6vKkbTeqIUqWYbtlo=" } } }, @@ -6226,18 +6226,18 @@ "copy": { "directory": "copy/range/", "files": { - "runtime/register/range.js": "sha256-HYsfnS/M/wjcD+spw64Qas+a8kndWqTvSRdBedy0U6g=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/range.js": "sha256-UOtb5bcowunT33yEodiHV5YKGl/OTUl5qSsO3xxwSHY=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/range.js": "sha256-E1UD7e4zjan+J5sC3GAZQNpX32Zeu8iAb+A2KfuUO/w=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/range.js": "sha256-QRunxTcE2W9hO8fpbtB9TIPALr/yUFibuPV86LgLThI=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-4ayZ4hpLNMgckII249GLN4LXptEvABeXopUcVCG8gLc=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-F3TYZf5Pysp2EfVbSAxBHmgiviXyRS3/dKjUdvZrzF0=", "index.html": "sha256-1VRc632ZL0iJ4ZwPDOH9ZKFqS1JtFx995UBRKpNUDTU=", "README.md": "sha256-lW1eqkbbrr3cTilmwEqgWHViJTPEMEDqDOHhsAizE1I=", - "manifest.json": "sha256-wUvuK/rH0R1M9Okdows+hEZy8BKRejoj45gRMD5zIx8=" + "manifest.json": "sha256-c4OvxZ71jQZZ5BODPEurTXAAcKqUI1t/27DhmN0l8gY=" } } }, @@ -6612,18 +6612,18 @@ "copy": { "directory": "copy/fieldset/", "files": { - "runtime/register/fieldset.js": "sha256-o9TJ39JjoD9lKj18M0HEJIsEaXvxYLuKg0BameLC9rQ=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/fieldset.js": "sha256-NnApETrqjlE4MbJmLICen1VVGenfbkiqjiNh9jSLgF8=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/fieldset.js": "sha256-zuT5rtNl3t8k1HJk1X7Q3lQIAgyzKBUsKFZPD0E/ihc=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/fieldset.js": "sha256-TWSyWZNRKgfnqI8T6d1EQ5W/mD6n0d8CqqP8ZNXAKgw=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-8VS+tXfjHW87aIScNUGAXsrsJ0qwScONidsZFMMFNh0=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Z916I2upHIzzffRAz/6w6FSTBwegAd+L49E9Juck2fo=", "index.html": "sha256-FbUV8k7YOMMErf8en/dGZNZE0nkjJvqan+FfQLgevVI=", "README.md": "sha256-dNh39iesY0kLTE75KP+a0WhhHDQpT+j04MoZgMmV4F8=", - "manifest.json": "sha256-N+k1sOyc1xn9mQPzsrZ2PMYAWXFZcnELwGvileR+b/I=" + "manifest.json": "sha256-YNW+PoKZwohuqWHAcQWYxQOGTXR6y+pebqXA3PZj918=" } } }, @@ -7235,18 +7235,18 @@ "copy": { "directory": "copy/number-field/", "files": { - "runtime/register/number-field.js": "sha256-hzql0aRe655T+FCjYFhxlfYh24YEAwm8mSKqaRvncg8=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/number-field.js": "sha256-XejyUXzeklfHnLge+zZzoxBqpQGWSXtTLGhXpkm4Sew=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/number-field.js": "sha256-4H1AixN0gdK1WGkj5AboI6P6f1J+4eTI6guRQiLwdXo=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/number-field.js": "sha256-cR7uqb1y36rf/q2olUxijeTw76itQKlbAa+rFz+FJbc=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-XO8T0IBA7SNqfrL29Rr4KPOzxW7QYgRQVO5YJ59Rmbc=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-wabUKPjMJ+zn/+oKJMogtcDlppICQ8zTGXEbhGwm+iQ=", "index.html": "sha256-5LArzp8P8o/Sx/BfjJC3wIFgD1V0XbJ+7wgFK1xiKTY=", "README.md": "sha256-ZNn4SinUkL66soe9hksIPf65yrk5SCJshryFP1N2GnI=", - "manifest.json": "sha256-4UO59ACgoGrblshjRtY9Nx6Z3wv201gT5Yl/YrkjOIo=" + "manifest.json": "sha256-d2tEAN3R4JL5f89dc9qeh5wT2Kpx2hJl39oTHMF9Yhs=" } } }, @@ -7744,18 +7744,18 @@ "copy": { "directory": "copy/search-field/", "files": { - "runtime/register/search-field.js": "sha256-oIExIQ80Xzt1d5Y8KclVl+lAi+cgOMhKMFNPBz8fEXY=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/search-field.js": "sha256-HCnoLO1ZZvDEqeON+Ir7Q+XChuArNr/tJ7H+lnVTJPw=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/search-field.js": "sha256-6LYU8HU+rH1uC262cp+QTcMOL1fOJadTf2sVIOar7yw=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/search-field.js": "sha256-DR2wccoQwBDsamOMrOnUSaYWdhk+1zRdrnB9VfaIthY=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-wwF2mPKTtvrFcPXYn8OoWoeJPj5KgkmPbjay/kNVq6s=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-HUFhtyi3m/bOmHYH5vU0uD/8e/TFVZ6EmUZzoucKCCM=", "index.html": "sha256-hCiVxJ7XVQjEcEeSYLpYgSmV9Wn9MIgxJm1EWMzoeKo=", "README.md": "sha256-aDgof37yYQAYKjMAPaaPxNDPtVVxOfCjHh2aT60B4xo=", - "manifest.json": "sha256-609B332CEGR2BZk/y6Wsa7ahXf1sJJK1iXbLzzNDGOc=" + "manifest.json": "sha256-USDdkZ8ckRRJEF/SU3bRLEXGWecX2d4N4lFUQW1RTI8=" } } }, @@ -8304,18 +8304,18 @@ "copy": { "directory": "copy/combobox/", "files": { - "runtime/register/combobox.js": "sha256-t7izNmL59Io74wyYT41Fq3jMXxWJ/5V4IeEkC0apDwY=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/combobox.js": "sha256-7kydwJcVW8U2c0ssJPwbR84tdqvYPN/lFqBuOGeDQpU=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", + "runtime/register/combobox.js": "sha256-m2UGZdlqKfsCnUJuIsT/I3mYjH6K0Y5R836lZqJSXWs=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/combobox.js": "sha256-M50QmcWZJm+1LBF0oMh7S3tuXjDoApW3kq5Lzf+s57I=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-8Hkgwo0uaQUx8y4ghR6eYfsYL07GWC6VT0p+F/wavGo=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-/SDEtn3D/9kfnULtpHPFEgK1FAkmwe+77gdxlWNewhY=", "index.html": "sha256-p9Z0Z0qJkFi41Gxp+ZcP2av6zsHe4VtOAtgfxnDq5YE=", "README.md": "sha256-d6hom7buY1pZpNug4Bx9SqSXvSLDY+cq2xwlZ2Fei/U=", - "manifest.json": "sha256-JN1xqFQwRlRkbdXeaWnCDAO5xaE514+8b2SFoCppq1I=" + "manifest.json": "sha256-BHwUvX1X6Rgb3rs2Pc1sNQvqeTdHabf6SjFGk2AmU1M=" } } }, @@ -8972,19 +8972,19 @@ "copy": { "directory": "copy/multiselect/", "files": { - "runtime/register/multiselect.js": "sha256-GvsBeg69jcyZ7oEUVcCdn1MKUx1TUf7RIO5QVAsXGH4=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/multiselect.js": "sha256-MllSXtT35z9jg4cXDS6YzVpSLSEHEdFav9snvf+mVPU=", - "runtime/chunks/advanced-CqBF0dSb.js": "sha256-ozOzkRU6IeVGBqU3XQ0aLledkAi9vcs8dJdMQutVevs=", - "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", + "runtime/register/multiselect.js": "sha256-1WE2XkDVU0w3W2wKz7GsaPQoHNCsroAW8HcfzuJg7Cw=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/multiselect.js": "sha256-sPp8OqCzF9v0hsxG/mWdadkKOIW//gyZ/Bng4A5c//Y=", + "runtime/chunks/advanced-BrFnVc0y.js": "sha256-FVberBpKO49P/WGnxa61BTxhYsLnnvMFInur/TwjG44=", + "runtime/chunks/markup-AopKpwOF.js": "sha256-/Dn3cWEmlRQzeQAPVf+C0AooVb1pdIQeNeqd1fQVoPc=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-mNyp6sPjM1B458gp8a1MSGzOFHVesIqX8cVV9P3tth0=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-1E4hftJizWZX+Gn6uhOJBXC2VAC62t50q2kwRpgS2pQ=", "index.html": "sha256-0lrVFcwbFER+XauYVRXJkM2wQcvKcobwcWzQsL4OQM8=", "README.md": "sha256-754Tt+bveWNGF8niAMoHQEB7D8SGYGEJhu6GpbhKpiU=", - "manifest.json": "sha256-KYY69hwFJKds9LVIYh6+0Yr3fDHw8TjMMn7maw9COdI=" + "manifest.json": "sha256-pCT8YyVDemWPdlGMBpAYt+GweW0jaodNFNh5FyB53NE=" } } }, @@ -9570,18 +9570,18 @@ "copy": { "directory": "copy/date-picker/", "files": { - "runtime/register/date-picker.js": "sha256-ffEEGjAUrXQXzVdMaSM5DtzrLavfYTdLxmkWhPWQRIo=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/date-picker.js": "sha256-6V4hlflxeVpDoj+uuaVEpTKm1ZKIyCYAiivLhpESyZU=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/date-picker.js": "sha256-2QI9scZ50FCzd1DsWatvh7W1DIyTKZ5FhrKPs84ihDM=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/date-picker.js": "sha256-rrcEetO6fITkbc8adFGTiWLPMv6dMJt7S3emImwYDZg=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-17l8tm/NKV8wNhq8EIPnmw9/+K4egrcSbiuLY63EpUs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Nho5WRdNWOIx9zrVkZR8s5NrC95hgRBVnvDTdnZ7qoo=", "index.html": "sha256-SxAGYroKCEemIb+5PImBbe5DAU1pOu9frv+8yu3oY7c=", "README.md": "sha256-7Nf1YMBxm1cGzO+rzOKvfqWgRfugAjR+6/WjnVo2qpc=", - "manifest.json": "sha256-LiBwzgSr30/e/fN9ddg+q4sCYu9syKXj3tCBtq107No=" + "manifest.json": "sha256-CxVQPORtGZItCKJdZW0KeB38sjR2gai9Y8SoJz/pE9k=" } } }, @@ -10153,18 +10153,18 @@ "copy": { "directory": "copy/time-picker/", "files": { - "runtime/register/time-picker.js": "sha256-Y3N2tnRzLjdmpYzxx3rCbl+joREEqSwDzaFTVHIudjM=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/time-picker.js": "sha256-8R5WT2w1+ieYWJkWby33LbGCbBuQiWHFaETY+vXANpc=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/time-picker.js": "sha256-OfeHc50DC0CCpDG6HtsOTCBHorWppUtU1rY98SCCb/c=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/time-picker.js": "sha256-2p3tnHMSvEtUF5fupvSa83suSSNzx7lNWyogBq+VDw4=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-fySG8CnltTPsU5F0+8Cbt+YUVtEAU2AAkDFqezc416I=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-RLfLhDEtkzyeISgOb1Njmp8QsxMKjIUzebwrMAg9GNk=", "index.html": "sha256-HBltgH+aaDfBk6fcYX4waQKdoApT3zk0+wUOtaTyO0g=", "README.md": "sha256-bK7PieiUKZ/3zwSldV/HlWMak7kwtWyvgpYy1YfAmbM=", - "manifest.json": "sha256-/ZoFdyjtITEpXf4lTIklavQqcxnnUbhOH6lLOQ0jtt4=" + "manifest.json": "sha256-dWGjEYZtZLRxT/qPO7RWBLUwAZeKkHO1zjPVxIOWYY0=" } } }, @@ -10791,18 +10791,18 @@ "copy": { "directory": "copy/file-input/", "files": { - "runtime/register/file-input.js": "sha256-b3BX2Mpd3hOdCnJZepq1gTZKBfvGMgxtEWnrAg8yfHA=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/file-input.js": "sha256-kE0QDQfY2i/MZLrABzvzfCatNUO8IQsU+q/AXBy6hW4=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/file-input.js": "sha256-ExE88VufliqZThHiVWLYTWVQgGqDWBCWbuRUBn+ZGV8=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/file-input.js": "sha256-IH4BuOvApw1/fBKt00ZvlyYSHfmgpV7+vme74RPPjdU=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-39WZRXEdIS4uIHh7bXmFulEjX4bGk2S3+7jZc7VyC/w=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-3MysNuXXyX6HzlWv0wFhnto4CU9Q/n0JHK2wx1ufwbE=", "index.html": "sha256-Mruf4SRnwaZ2RK7LaKRse5q9c4QKhDHgEgCAG4hyL7s=", "README.md": "sha256-fT5UasqXVH/Um8vNgVGEXNG0Pk7WZ4Aq+K44FBlAdpk=", - "manifest.json": "sha256-jCusOPGk/wROmZERAJfrwjFsdbxWEW0umySlqp/dE2U=" + "manifest.json": "sha256-UjWbK5yz9uM7Cug83FXK3r5b3ow6dJz0Cjc3Y7PUCiU=" } } }, @@ -11370,19 +11370,19 @@ "copy": { "directory": "copy/repeater/", "files": { - "runtime/register/repeater.js": "sha256-+BJGwFC4ULsZj2rUXucqIP4bkN1LZVFvuFrN1eK5zsw=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/repeater.js": "sha256-S5GJEE4PdeXjexdZXmIgJnjsOURVZHpQCSJzc+huJXc=", - "runtime/chunks/advanced-CqBF0dSb.js": "sha256-ozOzkRU6IeVGBqU3XQ0aLledkAi9vcs8dJdMQutVevs=", - "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", + "runtime/register/repeater.js": "sha256-eOxh9asjFElUMBptJubnb4sagYVPb5+yydspzDqugOE=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/repeater.js": "sha256-FOveMEI56LVJDMyXlEMbXGE9D0/LX85DQ9meCqa8G74=", + "runtime/chunks/advanced-BrFnVc0y.js": "sha256-FVberBpKO49P/WGnxa61BTxhYsLnnvMFInur/TwjG44=", + "runtime/chunks/markup-AopKpwOF.js": "sha256-/Dn3cWEmlRQzeQAPVf+C0AooVb1pdIQeNeqd1fQVoPc=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-rx26lMPjdf1Z/n5dSt0W680aeH4/Vf/JHj+aVD7Yd0g=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-DSCQzrRbDwFOKtw5YmpR+3oYWMIBJFIPnJpes5bSMPY=", "index.html": "sha256-NcmqHhIALqiMTfxl0qPl+bYykJcUXvHzjXqS4Po+QCI=", "README.md": "sha256-iFFjPHWI+gh/aJ7+flDL4I/Qaclwv1yCfGRuJ06o6tE=", - "manifest.json": "sha256-WHPo/96QBm03LMBbG5dmCIDwDKsHFHH4485Ks5GK3Yw=" + "manifest.json": "sha256-ddOPfDHZVO+vtT2sU0ZPXvbQtlakjuAS2w+Atm3Qsgw=" } } }, @@ -12018,18 +12018,18 @@ "copy": { "directory": "copy/wizard/", "files": { - "runtime/register/wizard.js": "sha256-j1MmLx8Vq3Ou/t3+hX/UD2AWZq1D7MRHwwvCLStmpFw=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/wizard.js": "sha256-iMzWia0NibbI8OZR3lt0VNBXQXq/OjK7Mz8n9BHkt5c=", - "runtime/chunks/forms-CE_hP1hg.js": "sha256-uOnoMuSkUbm9C/GfR+PDLYCykyHOQ1Ni7g59c4YMOS0=", + "runtime/register/wizard.js": "sha256-3aACVGrEwAij3/eXLo2Kj2WGiM2PDHgexOEY8UmD/ro=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/wizard.js": "sha256-qUPBej2sL10ar6pmuJhdA1Tk155stiGvejFAN+ep+P4=", + "runtime/chunks/forms-C3u5121t.js": "sha256-DymhKeiaCcQj+DmkDxoEwP0Md4YxiSpCxyYS4eiMnV0=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-DfWE/GpjBHHnAxchKcu5pTgCo39mSS+V9uDHjFqFwmA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-T5EJ8DcqnD1rFEoCwvdUpmBCh0hH9dJSmq5oOkC+mi4=", "index.html": "sha256-iWmkWU3qxvtjRPPPDLUFT5Sd9bw1krZug4ntOGEYRIU=", "README.md": "sha256-B9klMh35GlqO5l2mxI77I6x2Gwfl8AMNSH6P+up7GdY=", - "manifest.json": "sha256-f1tphJBiywczN6ta9PIme/jOZTIn1DL09FjKqrLgBzw=" + "manifest.json": "sha256-Vf34na5KixdN06CY/a3gIokAxAGD9dfyNynURUGHv84=" } } }, @@ -12917,20 +12917,20 @@ "copy": { "directory": "copy/form-builder/", "files": { - "runtime/register/form-builder.js": "sha256-tU2ZvWo2T/MuPBB3TOjq1zh7tLWYnPh0JidHFW7mDgQ=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/chunks/form-builder-BvWZCBPR.js": "sha256-co6mxdcVOLnQNkM8uCfl8kI63k0MGZh/3Fc+rbLIZb0=", - "runtime/chunks/form-builder-BRIaVVFY.js": "sha256-Tp9FV5rv/ZMCey3CeQsnuBF2JLbIPx+fHgNluS3DeBE=", - "runtime/chunks/form-workflow-BKRLylvq.js": "sha256-LcDxqsGpnid91QErVgWLIaXtB5KQS8Uad6Q2shJ1Ohc=", - "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", + "runtime/register/form-builder.js": "sha256-oXBX37RV8hqaewR2lwDVwOl2j/msYQin6hRz9lX1Jx4=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/chunks/form-builder-CkeTBQe-.js": "sha256-iRHlKYYOhwufdLevaEyOgE67JBEu4RoXRoac4B2A21I=", + "runtime/chunks/form-builder-DbZUZMo1.js": "sha256-pSdb7sCB5w/BFrtZppLI60CobZa9ao5sqyQkvChry2k=", + "runtime/chunks/form-workflow-B183Y5gc.js": "sha256-wj41Umu7N2n0VIHJWCVtrmjCwuzB8U0k+mah4rAekQ8=", + "runtime/chunks/markup-AopKpwOF.js": "sha256-/Dn3cWEmlRQzeQAPVf+C0AooVb1pdIQeNeqd1fQVoPc=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-AvaSTsUjkZrvH982LEeySHgVpBYhI16Uh3XGc3F36g4=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-WUjDiy4tZKp/CS/g5I/hIUQY0Mci0zrItPW5k4K7As4=", "index.html": "sha256-640gpCzARRbVwXUct1TM0s5GcegFiYevcWBsg7VSOqI=", "README.md": "sha256-MGlPh4CEW6DLecBSj7Ym9ww3NAGe8r5V9uANRpZLY48=", - "manifest.json": "sha256-a5DKdlqeMfmBODkbOZ2FKf/u4r5l4abtTYd4wZ5w9vY=" + "manifest.json": "sha256-Nc30zX+hmCj/+Axho81JjVGR9rs0F9WjUl5R9k9GjWk=" } } }, @@ -13331,18 +13331,18 @@ "copy": { "directory": "copy/tabs/", "files": { - "runtime/register/tabs.js": "sha256-l7XwbcEZ8OmMB88/x9pUtN1ecLySUw198ASEleD+hZs=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/tabs.js": "sha256-2AWArhhBdqbiE1BHWeiumCgXyKi847dzv/cMGGfCfuA=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", + "runtime/register/tabs.js": "sha256-vuNpf0Ff4n7Hgx8O4757u2GYg/zd7qZ0qR1yYzIIJME=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/tabs.js": "sha256-EZw8dHljPEIaVDnuxpR0JDUNswrzy2tdcXiSySBYCyo=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-fstv2PtC0k8ABx0bciCb6VX0pPTRl3oa8iGdR+6QR0Y=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-xe4UR+a4C9oNodr9UlW5OGE5DR5R9JErwW0UAalo8oE=", "index.html": "sha256-Lg89PWgkBGwJzhoQfiPykrsJ82dYys7yJEdQ1+tHpWM=", "README.md": "sha256-uBwdwc6EkHrqha/dCs9PWntoU1l7EAJb7Y6nx+zzrqI=", - "manifest.json": "sha256-WclRBxvisEeduXeY0eL9756ei20T9Z1+wS2GJ1B0yx4=" + "manifest.json": "sha256-nIGTh6QGw8FBPOIA6CmOHjxQvCZeTD4GIYKChNA+LH8=" } } }, @@ -13680,18 +13680,18 @@ "copy": { "directory": "copy/breadcrumbs/", "files": { - "runtime/register/breadcrumbs.js": "sha256-TBQ50OLAdUaAgno93QicDrgSoW5MfLyWLXoR+GWyw0M=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/breadcrumbs.js": "sha256-DgJ8uy8nkN1QOm3/zq3cYvs7xmhXCyPkXdhu3CDEE00=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", + "runtime/register/breadcrumbs.js": "sha256-T+4ZMhNyFraW/V5E84ueE/5MWurZ2UfOdAkMEh8DVa0=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/breadcrumbs.js": "sha256-lttQVA0QJicYwLEjh9+fV4T6Bbz1HugXAzgrH1lYDuw=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-+Zc2EEKW9OfZl8s+wFiHlzjJHlyVTyGwZDbPlyRKx4A=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-W9qk0XtcetNK1me7748lByEMSMUZyP6NT//vet/Kt0I=", "index.html": "sha256-Q8aZfYganYA/1sF70oMXKr7Fn/icqzSWVNlbxC7x00U=", "README.md": "sha256-KtiYxcVwfGDIDiTnYI/c2MhmVKez7eLztyU55QJQXgs=", - "manifest.json": "sha256-PnPBWuAuuwRQb41eezSDdJeQfhCsDD51EPmo4ROi/oQ=" + "manifest.json": "sha256-CJpFbChWwRbAs6PLzZCwhgnD6Rd9eel8zHWhRjHQ/14=" } } }, @@ -14073,18 +14073,18 @@ "copy": { "directory": "copy/pagination/", "files": { - "runtime/register/pagination.js": "sha256-brgdYKMAD7bcv2S/lK/pvq48lAK2y+31j4L/TNZAAAc=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/pagination.js": "sha256-B00TORk80D679cwO2BDfd3MFyKRhgzAoaWxrqC1AoYs=", - "runtime/chunks/tables-Cjr1EIJz.js": "sha256-K6BF6M6xNawgWdL+NIcBRZmY98j45o69tBI034Ks4Bg=", + "runtime/register/pagination.js": "sha256-Y/I0I6NpUS93DpmbrgeeMSQ6Qz20igQzG2hwhcqaEYo=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/pagination.js": "sha256-o7hAhquWpAuaROFwNjCnsuoFE1pRQZtC9jr6DPCoIuE=", + "runtime/chunks/tables-zo8ebTOo.js": "sha256-+LRPZmFKPk0oe8q3HDlfXCXkloBbkRbiFHVHczc3GEs=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-Y82QrGBuuCOolKEvjfgUe1uRkUY8RAPoLEiVsEUahxg=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-jp4BjPewAxszUnraKXf7iG6Zty7ZB7J8SdFyHQg7hL4=", "index.html": "sha256-QfAgrl9jbgESweQA3i2v7JR2ghU8LgF8X0cY9hqDnWY=", "README.md": "sha256-CkmYa5gHgFCQLGpkV2WpwdaxjhezkCTRRw8d9KDRUqg=", - "manifest.json": "sha256-42MfBra/mPVu0124rOIT+z4o9+cJiVEqiO4Pbd1vUAY=" + "manifest.json": "sha256-abLoECwx+t8UmiTTJTwip77GnqDQuK0CufG+rVps5rM=" } } }, @@ -14512,18 +14512,18 @@ "copy": { "directory": "copy/sidebar-nav/", "files": { - "runtime/register/sidebar-nav.js": "sha256-wezN/wQaG+kQGmgqJIj3iSl5mFjjKr0DJLl9jLsnRFA=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/sidebar-nav.js": "sha256-DZRlRYGAhBJm3yZ1nqAoW67+PcYUqE3uCTEEnKa9NFQ=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", + "runtime/register/sidebar-nav.js": "sha256-4Bq41zeEEBKMEmVQYRFSAsKz16A6HbWtI61B0pyIR1w=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/sidebar-nav.js": "sha256-/IIf4o9f34122fyLRdFcxXOsCbG1deNnKEExODzSGJ0=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-LJ8LLDvQsYO50EORdep12yfyTFwnO4BxbDzOwHYpciA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-LBoiPSLgtVIozM1wEFWbV78DaFWbIW+6OgOjaCSim8g=", "index.html": "sha256-dOEwMnbaj98YMfD6CXUGCi5NU1carEGBEl7w+wp1Aok=", "README.md": "sha256-QjtvSq2sHwF8bsMsDu3BpvOyATxZ0oanPWICItjaETU=", - "manifest.json": "sha256-VO6xveM5OIpLar/RKZxpxOufr5wR8nQZ32JA567smyk=" + "manifest.json": "sha256-p5ADfs5E5mPaPEcwwIweDj+AeqRSmA4k6sMHe5WZUL0=" } } }, @@ -15038,20 +15038,20 @@ "copy": { "directory": "copy/toolbar/", "files": { - "runtime/register/toolbar.js": "sha256-0i+oWvmcjNoFTB9ChlJSM3r3Ig4bYjlkdy/lkmNBlmA=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/toolbar.js": "sha256-kGWjidatkl+BJM+S2e/e9pYaok6mLuLLl520Nn8h86E=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", - "runtime/register/menu.js": "sha256-6CvU7Rei9lC+olXvluxdbCPqh46GrPSvB2MGiudiMTk=", - "runtime/components/menu.js": "sha256-As/aVex/jKXrmY4x/rG0tVMVUij8ZLPXK0kKS4ZBpSQ=", + "runtime/register/toolbar.js": "sha256-Gf7THPkn4x1hVyTl/jXRoGd2Oa5RL8dK8uqHQV+pqxQ=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/toolbar.js": "sha256-/Uxx9EzorKPSd2FGVPpk5AnASvRBGVfcGONUJd8x9LE=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", + "runtime/register/menu.js": "sha256-du/4u8ykElicgf7iZHv6rD5yz/4njOxzodjcqCcr0d8=", + "runtime/components/menu.js": "sha256-qz11rQvGk4omYnKEFWVz4SXD3R4xn/UhG0nt4oqFtJw=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-zD6jRNAjuf7XM9+QaxwzEY+F2cFUrQbgUKNLTCc7Q/Y=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-MRU95stqvOm7gd3wzi8XadrYOLU9MRKqdwFO/bmSaPY=", "index.html": "sha256-AJ2jXzyPYjQufetc6mGuf1SQv8HGS9+yyaOcQo9pOIQ=", "README.md": "sha256-jPzt7MdgG4yEEJJ6qWZk3Cgw9KNNNHEKkwz/nnKK3co=", - "manifest.json": "sha256-PwYY01GF5N9/s9FdXsJtMVY6WsdNtZLfui+KNtnqQdM=" + "manifest.json": "sha256-Xg44V9lbRGNYlSs23Ub7Ihw+m6Mi7pgdqp5SfpGomzU=" } } }, @@ -15568,18 +15568,18 @@ "copy": { "directory": "copy/menu/", "files": { - "runtime/register/menu.js": "sha256-6CvU7Rei9lC+olXvluxdbCPqh46GrPSvB2MGiudiMTk=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/menu.js": "sha256-As/aVex/jKXrmY4x/rG0tVMVUij8ZLPXK0kKS4ZBpSQ=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", + "runtime/register/menu.js": "sha256-du/4u8ykElicgf7iZHv6rD5yz/4njOxzodjcqCcr0d8=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/menu.js": "sha256-qz11rQvGk4omYnKEFWVz4SXD3R4xn/UhG0nt4oqFtJw=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-k4+o5GOHUM88StftYskfdyFUCI7mkb7z/Q98q6IVoLs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-0SXVO1pxUxzA5mgZzG5YXw21f3G/n81DtP3vy14Nv5M=", "index.html": "sha256-nXwk+/iADkSMB6qGYcl8yRJh5+nE6XQAdTdECvt4i64=", "README.md": "sha256-ICc5PzI3f6/Kpyf9KXWame8aNgGPR8JKtgBhHc9HrsE=", - "manifest.json": "sha256-eoVX7JW50Ns1bF3H48oMiBwHQpVujXmyHEE5ghJMW4g=" + "manifest.json": "sha256-CNL3cvaGQXvHWBlPVha2GHckzxSzoKgCy5veNKlqiS0=" } } }, @@ -16215,19 +16215,19 @@ "copy": { "directory": "copy/command-palette/", "files": { - "runtime/register/command-palette.js": "sha256-SSDEUavPG+KZSHsxMuoACxT3IKIhzg9LNpUMj+pS9Gs=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/command-palette.js": "sha256-GlMjxlVVzdC74Yr4LjWbLwXWGrHkFnjBaJ4o9rJw9DE=", - "runtime/chunks/advanced-CqBF0dSb.js": "sha256-ozOzkRU6IeVGBqU3XQ0aLledkAi9vcs8dJdMQutVevs=", - "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", + "runtime/register/command-palette.js": "sha256-PedlHrZKS7ibQjvoHExGQ+zxHgj8xqJ0E2ymlCfKQfo=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/command-palette.js": "sha256-IQKcYTVvuVtfGr7iErnA5SPEPVN58stlc12ia6WDx44=", + "runtime/chunks/advanced-BrFnVc0y.js": "sha256-FVberBpKO49P/WGnxa61BTxhYsLnnvMFInur/TwjG44=", + "runtime/chunks/markup-AopKpwOF.js": "sha256-/Dn3cWEmlRQzeQAPVf+C0AooVb1pdIQeNeqd1fQVoPc=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-tiMnZi/dRu4gB3RP0zxXVpTrTvFZsCYaugfulxBVhTk=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-mNRkLE+yYA4PARM4rv5bXDj90Oq8yxQLPgoUW8bX6ns=", "index.html": "sha256-2yjQF/1liVxnaJ1hZ9hxFhuMt/x3P0EkNlqVnXroNJ0=", "README.md": "sha256-KLn7bklioLvnV4bRDAgf3A5aqqCSezXa9kKARSYCUcw=", - "manifest.json": "sha256-tjArMCNHId+SnS0f3ur35httBepWV8sCymDinMsnVjo=" + "manifest.json": "sha256-XlHU7U8vdCo8JeGY0CcOe8/lMvOWTLcOQbJYUToe8FI=" } } }, @@ -16556,19 +16556,19 @@ "copy": { "directory": "copy/tree/", "files": { - "runtime/register/tree.js": "sha256-5FC2B/6Dr2k5l/nTb9KKizslYbXmQxe2nEoLuYG6zDg=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/tree.js": "sha256-mYl4DYRuChSjXkRwM7LaJ31aYQZlvzP0RgTYmuNdC9U=", - "runtime/chunks/advanced-CqBF0dSb.js": "sha256-ozOzkRU6IeVGBqU3XQ0aLledkAi9vcs8dJdMQutVevs=", - "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", + "runtime/register/tree.js": "sha256-GkpgoR9dpb/ho4x6diQOMGUvBv63XZ0KfaibFjm74gA=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/tree.js": "sha256-P+63dC5MB2gKl/raxboRMQBCkbmDE850SXCmGt09e/o=", + "runtime/chunks/advanced-BrFnVc0y.js": "sha256-FVberBpKO49P/WGnxa61BTxhYsLnnvMFInur/TwjG44=", + "runtime/chunks/markup-AopKpwOF.js": "sha256-/Dn3cWEmlRQzeQAPVf+C0AooVb1pdIQeNeqd1fQVoPc=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-znFzezcYcv10Qwb2tH/UwaG4XQgCXophAwo2Z8cOiyg=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-F1zSdM5xw3/jlndjR4iQRRyZ7K9gfkgofh1Oin9xUAo=", "index.html": "sha256-/VmRV653lNaKNt7NO3oiJk/gDJfd6DAwSN1hvX6+viA=", "README.md": "sha256-rkAg9VO8TxgNCrXXP8dhUJ24Zori5pT/6k3w7gj4ixA=", - "manifest.json": "sha256-0GYN1Udf5ShojtuoMvLc3+3RUgiFtLW7Aao6WiS2uqg=" + "manifest.json": "sha256-BUIBqmDTbjxpeKSKfVvw3GbB6dqlb5C3mRibn0Ao4Mc=" } } }, @@ -16877,18 +16877,18 @@ "copy": { "directory": "copy/disclosure/", "files": { - "runtime/register/disclosure.js": "sha256-aIVSvVhr919KN1yvujNgB9MkM76nINbjI5fn2aI15hU=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/disclosure.js": "sha256-+8hk74Zg9ZUq3AstqnrP14hMWYJ2J3MQ8RCtpk4njOs=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", + "runtime/register/disclosure.js": "sha256-riSMKtiydJYp+gWIuJjvZQ0pyMKP1gGwilg6ENPUQyw=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/disclosure.js": "sha256-+iFBNYQitu+xCVINfUUYfDi8EX1/Lpn2cpZEvFr44os=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-M/UOvBwScEgDLtRZmuBaxCwOBb1g0hkfyHqaxsEDfHk=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-ZbpW/j8ZGKofIgL/uVEO47xXhxXmS2mrK5w32n/BWZA=", "index.html": "sha256-WhPsfoYZDJ7CShvFToWy9ysUDXDtzvu7SXHI+dsddnA=", "README.md": "sha256-eHT7DdGUFZxUFoiTNsB5j6dKCRG6kf9fT0gY1oSBy/8=", - "manifest.json": "sha256-pMODL78LTWx5czys20cATaHYiUuOfzpWx9mq9jiVF6k=" + "manifest.json": "sha256-R1qmwlzIBtRZDG/qaSsnPxCudK0VFECAfn8jGjFtV4I=" } } }, @@ -17175,18 +17175,18 @@ "copy": { "directory": "copy/skip-link/", "files": { - "runtime/register/skip-link.js": "sha256-GO29Wu/J6tcKAaNSyJEft5Nuiyn1QXF0x+VY1acaNuA=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/skip-link.js": "sha256-MomchP1kmj8/eRX8uVLTPeXPPhyYI18353abxwxtqTo=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/skip-link.js": "sha256-rdQErALjG6gRS2crzShW/TexAUbYpuBEGDW5L/xETEU=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/skip-link.js": "sha256-OzQweNJslHEVKrG1S2NnaBeW4GQAlBmb150UHci4dfI=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-AX9f8HRHYyMt1utmAsrIP+UncKsDILTwMv4qUMxNku0=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-TllH5VfEO0Xn2+KsNK2k/W4RJWPv9CVLWE38btvoOpw=", "index.html": "sha256-g9qP8QdXNXioXgABunl8DwcIBtkCTZH2B6+LuBrOPX0=", "README.md": "sha256-YX3Ch7JuUJRqIpsiYPlIc/09irmjC9OLqMTSPNUidYM=", - "manifest.json": "sha256-RHhopEYfYYCAIJsnNYh/snrzL4ikhKMQto16D6RM2bc=" + "manifest.json": "sha256-uT5+48pIlyjWHblNm1mbvUOs48/t4rAkdikJ1USnBl4=" } } }, @@ -17568,18 +17568,18 @@ "copy": { "directory": "copy/card/", "files": { - "runtime/register/card.js": "sha256-4IdkxATA99m7+u4hZzbgLzxNtZyQcI8WI8kkDxErCxI=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/card.js": "sha256-CE1Pt81XkHCmaZj7t3LqXTUnuvHd4E3/Od5t2v07ltA=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/card.js": "sha256-zMiNbkc2DBlaA01E05Odaecz1JA1cOewK1N8Z3aANew=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/card.js": "sha256-+1yNt41KPhmbGI3BqDj0s6zM8B6TeVyfUnzwt+kiAPA=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-FIugfi7dJgtnME2RJdIYZUQl/3O/WVR1fu23onC7U/M=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Rc0IwITP8X0cKscYMBt4LgzFbntPHkCAdDQ4xLh2LXs=", "index.html": "sha256-2B88t8s0Q7ugu+AiqBFD2B4OGRlJDRiO0Sz6gtWNyJ0=", "README.md": "sha256-7NvZudM1FuKwW/ZySKs98FmFwxwir6nLM/lGAvvcI+4=", - "manifest.json": "sha256-1wGcxPvwkLOFG+/IrgcVNc7OWwpt9Vt5X40wEJxgHYs=" + "manifest.json": "sha256-+ZDgWqa1Gm0/ZbS3kd5tiksKBofhb6/lIpaH3DyKg8c=" } } }, @@ -17979,18 +17979,18 @@ "copy": { "directory": "copy/list/", "files": { - "runtime/register/list.js": "sha256-f4HxPopmKcmXd3NOYv8arFYm1XmjhvpF0kbNynVYRUA=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/list.js": "sha256-X5HE772qpMx/n9b3NU6shv9zZWfmY9cjVn/IPAjFFMY=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/list.js": "sha256-a45MSP7U1eidIIzXWaMOiq9jf/+2F55E2LMAlxs0y14=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/list.js": "sha256-HjtEbhFT1/HcbIdaHdYeVWRI7h4AixKYxqdBxWVJwwk=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-rYecTkHR0B1N85CpEe58zzTavkIhRIQVzj50yKfdefA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-tiKX+fFUPCsBJEryliaQ7y9RhU4zlh8aEqMJ0aSO8Lk=", "index.html": "sha256-w1eB6AWS6U0cM/ElyxhXOk1yDvmU7RDilyxFWSKCjJg=", "README.md": "sha256-lw1NGV62/UGys6imJuVkK5qPyHaJqiOgSEuHCgehwNc=", - "manifest.json": "sha256-5oL9lUt2Rh7SnDKawm1o+76qI3BRs5D6Fv9zEInHNqs=" + "manifest.json": "sha256-vpfcp+3Gd0lvLGq4BdepfWusi001Xfcvl4pLnGkD3wc=" } } }, @@ -18274,18 +18274,18 @@ "copy": { "directory": "copy/description-list/", "files": { - "runtime/register/description-list.js": "sha256-GxP5SJuhMhu1hTHJsexrOw4T0UPxiW6YpB5Ekig6NG4=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/description-list.js": "sha256-yFwjohrGKRZXL7ylzdMxau2tHWLBEqlCrjhZFLoV5ms=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/description-list.js": "sha256-3osvUC9RVQ+Zm7/LnA1QxjmPZY3uAc+I2yqkHiwsBxY=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/description-list.js": "sha256-n1agfwnHxoAp1znriJX4mVEszfKtm0Hwyy9AYRVRbkg=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-rEMzb+R626s/u4B9UVumgQsD0pKkWBBP5+VSfJrPCLM=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-h2HPGz9Kz0LvMiuTC767wAQvYHOVVmffDECwh46tG0c=", "index.html": "sha256-w9bAryqOwOepebsvi1B9fr1xN+O78bNPFqZgdwfg5do=", "README.md": "sha256-RrAu5lsq7QsSDTX+KygEzIsHJphBaeLyKmqBc+xa5G0=", - "manifest.json": "sha256-xpP/lv9etnoSHKftX4rqUvDlQ1KZY0EeEjnYOHqyD1A=" + "manifest.json": "sha256-g7R20basqOzoGcQG1wExdudMw/U/b406QmhHIKvRdeA=" } } }, @@ -18743,18 +18743,18 @@ "copy": { "directory": "copy/badge/", "files": { - "runtime/register/badge.js": "sha256-OMhgJ1tgBmSwhSWWFds0Npmgs46ZFUk4HYOnBGAntC4=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/badge.js": "sha256-7aVCilfmosfSHQDe+hY74Ms2tAC1jMlxtTExgZ+istY=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/badge.js": "sha256-56Kyt+S1p0U0oomxduPHzI9FVOdfq+QkEirj13HbH24=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/badge.js": "sha256-FlhaqGV0H9kpUnPPf0aDoS4RsvSviuRuZ2oCn+jy9kI=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-au/P4qbkjvG1QpFUYQDc35IhSbbhmFRxoXhu7zPifn8=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-rXaOLdDbEK5SMtYsw5TegOMtcnLijmgtU07RVrvJx8o=", "index.html": "sha256-vhJcM8fdSzyuaUlcyXa90v3Bjkc89EZicjoRTNChWQM=", "README.md": "sha256-5TsNDY9d5k6gLYa4KQycTh+1uwvXsoF0XilR9xhKVVw=", - "manifest.json": "sha256-EQLMi+/s/9/r4jBUNqLLHB9a4hXAxwdJbe0EwruBchU=" + "manifest.json": "sha256-bkgRLHr49b5qbJcZfXpVEjzzhdlPw3nsw13B1W5ooWE=" } } }, @@ -19134,18 +19134,18 @@ "copy": { "directory": "copy/chip/", "files": { - "runtime/register/chip.js": "sha256-H45do+W8XNxsOyAgO7vOSM4Wm6HfTun0JETK6F/YGRo=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/chip.js": "sha256-S45gQt3C5/jkmBzAtETNlZkOIiP4jPQEUcJa7TAulk8=", - "runtime/chunks/overlays-BwgpF4jI.js": "sha256-NAd99OT4kDsFp8IHscKRus2jY6XRsq+GMzplWbJsY4U=", + "runtime/register/chip.js": "sha256-eF+2aWon9lf3LkH7QaQCkxFOzWUMmNMVKWA7fqgj2+4=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/chip.js": "sha256-MJ64P3LJsDD8m48qHWKCQnD9uybijjnCWkqC25A3ElI=", + "runtime/chunks/overlays-BW66WXLm.js": "sha256-Z9etmUpuDuykKbJkriLMz8iiYnOP9uMUAshKwoHc1I8=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-358eNya4c7h47XJC5dFUZncxpjkl0B9HRfRfxwVS8so=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-yjXdYrZ4DqpcZ/ZDGxD0cgfYY/xqj0qeSkX1dJmVhfY=", "index.html": "sha256-k4FZCUqK/d9sBff8dKJJwQW99u70Dw3zXRzcH3da314=", "README.md": "sha256-Ay+51qOAHcbN22QHsMfcbrA/66D52crp5OlQCHyMYmg=", - "manifest.json": "sha256-G6wsd9o4sObyBn2pSMbPZcb2tX61tF6Ie4kt26HgIDA=" + "manifest.json": "sha256-CU5wNUKgI2FlTYYXz6aqRGpR7umv1yBDqnIBuABcsFA=" } } }, @@ -19424,18 +19424,18 @@ "copy": { "directory": "copy/avatar/", "files": { - "runtime/register/avatar.js": "sha256-vcm/QDMxjQTfPDcJ7Q7TIwknLisAbwTawOMwzAfjzhg=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/avatar.js": "sha256-eST4r5/Ji77KAR4qwQ+HUIyQL67gllpCSiBqpODqeW4=", - "runtime/chunks/display-Jm9bAsnb.js": "sha256-qZb1g04piEwY3lfFJwMe+0mXR218ljtVi8mepWxrFv8=", + "runtime/register/avatar.js": "sha256-ceYN69xE5V6HfLxlvtDkJ8xjTb80vCJ5ICs/XsmR/2c=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/avatar.js": "sha256-HKb7J6bzaF/F3ze8C/vzB6L9eaHLCswImQNP+dAE9dM=", + "runtime/chunks/display-l54fb8vw.js": "sha256-xfzo614uMLlSbZc5l+o4vHvrL8yBjQAcV/HJdmPUJ/g=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-5uftL4p30t4ItPscyYR/4jS31cRz/VU0Ga2CL/3fjhg=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-R1Q+6UFu76jOlVP9cadBrMxVS3+Yb2JgIDkcnKxWvtk=", "index.html": "sha256-0+odnlYi/Hd9a2qUTsn5PJwVUk58HsFdCUO9S39AFlg=", "README.md": "sha256-u+Rv0zskk5yOTH1pAzZ2eB3pId21guCqbzSFwIC5pcw=", - "manifest.json": "sha256-h6E9Gq/zG5cpoR8salWCBZib2LAeN/HoEWUAjUuO1eM=" + "manifest.json": "sha256-ilxLEKfMT5nFnj36Q8EbpTR2cUsrKtPqehskB4kYJJA=" } } }, @@ -19860,18 +19860,18 @@ "copy": { "directory": "copy/table/", "files": { - "runtime/register/table.js": "sha256-+Up9lgrfevvvIUF9vuOOwKxw0nDOAU/VctLLKZ73sd8=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/table.js": "sha256-CcoLzw/lwTUDE+3sCYBoQQoZAlE++zhK1ZLZELpyYN4=", - "runtime/chunks/tables-Cjr1EIJz.js": "sha256-K6BF6M6xNawgWdL+NIcBRZmY98j45o69tBI034Ks4Bg=", + "runtime/register/table.js": "sha256-piUGaWv54e50o/2v7ww74yydrQnhGV0dRB9chVItIbQ=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/table.js": "sha256-lZtEzQMmdL7Y6J+TrdKRP9sFsZx0hQRaCjVy3HVN8pU=", + "runtime/chunks/tables-zo8ebTOo.js": "sha256-+LRPZmFKPk0oe8q3HDlfXCXkloBbkRbiFHVHczc3GEs=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-FsyIsB3w0mFPeVNG2Yq+D6/h7aeVKJpEALxaD4j3afY=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-eTlfzsTldT7TjA25qNYpX+MAAskuYiA9Y+zZW9/B+MU=", "index.html": "sha256-A21rR2XTwrPTwfZuz8lsPvFXneXhrFjzL0/Xdpfmo6o=", "README.md": "sha256-hZvyqPLVQoQuOKc7t2j0cESQRW84E8XfCL/ad6sXIdw=", - "manifest.json": "sha256-tvWu57ODVYxvIxTP4E2tRSr1XXn+jCQ6wIPEYa1/jAs=" + "manifest.json": "sha256-B6eCEQB3vn4XFs1hZA+wamnWIpSWQOrAQMcrIkoUCE0=" } } }, @@ -20456,21 +20456,21 @@ "copy": { "directory": "copy/data-table/", "files": { - "runtime/register/data-table.js": "sha256-wrLpuRzCJQhN8Kx+gdh/HOPhsNQP/wrnopu8NmJsUm0=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/register/menu.js": "sha256-6CvU7Rei9lC+olXvluxdbCPqh46GrPSvB2MGiudiMTk=", - "runtime/components/menu.js": "sha256-As/aVex/jKXrmY4x/rG0tVMVUij8ZLPXK0kKS4ZBpSQ=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", - "runtime/components/data-table.js": "sha256-Du0JOAv8n9YEK04c217gbbmS25D1Yfx4irEe/DIPLk4=", - "runtime/chunks/tables-Cjr1EIJz.js": "sha256-K6BF6M6xNawgWdL+NIcBRZmY98j45o69tBI034Ks4Bg=", + "runtime/register/data-table.js": "sha256-Q9RijAjLomTWYsCq2oBB0nqzctnSczqxn2SN/kO9hEo=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/register/menu.js": "sha256-du/4u8ykElicgf7iZHv6rD5yz/4njOxzodjcqCcr0d8=", + "runtime/components/menu.js": "sha256-qz11rQvGk4omYnKEFWVz4SXD3R4xn/UhG0nt4oqFtJw=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", + "runtime/components/data-table.js": "sha256-RCZWFa2cvBMJVcELbxOnA7yDNokUGtGXj1ok+Xl+l2o=", + "runtime/chunks/tables-zo8ebTOo.js": "sha256-+LRPZmFKPk0oe8q3HDlfXCXkloBbkRbiFHVHczc3GEs=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-T5PnYnMx2i60rNgYfN/tfLrncLf9cAlC4gsLpnSw/b4=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-FieIuPCt66UIxpdAH0wuPBOrPEVXUqjJfyWMyCdO9nI=", "index.html": "sha256-mdaJIGJ1LweEct6N9Nr+hCoVjZXODSmyFsSgII8UMzQ=", "README.md": "sha256-bS0eRb53j0VgRsRbFv81sqclvoIS7Uv4m/FIBGXMqTw=", - "manifest.json": "sha256-ZXpisN2sD2A6zlORJ12emoU2f8SpPNEjy3p0bGcsbIk=" + "manifest.json": "sha256-wRKFbyntVQNJhwQa94bAviNO85PO/U2WEgopjQS5mKM=" } } }, @@ -20755,18 +20755,18 @@ "copy": { "directory": "copy/timeline/", "files": { - "runtime/register/timeline.js": "sha256-uXCGuHnZsZSnhQMl00/o559cmYMJo79IrZ1j4ZNySb0=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/timeline.js": "sha256-qOO9Ngp7Zj87zq3HaROWETcECMB8hz5rgR4ryNoEh34=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/timeline.js": "sha256-r6uPm82JiaBwzIf1SK006gw7WwY6ufiNxUnMnb5O4sA=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/timeline.js": "sha256-eRmNcK1XzdBB4hBBB4W6Hj6xUS2nNVfEv3BXw5hMJ3Q=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-Af6JACyiwzdqViRAgkXYbYmHSNOZKW+lyj7uVYBMHkc=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-pj/LmsP7e5l3NZI2ZWOLcerU4j0Vn1w2EloUpExz0nw=", "index.html": "sha256-8pkUBLof0Lbt5c0AhMfnzIpsfpfVFIObjqvMlRbud38=", "README.md": "sha256-CNaX7w50n7r2LnTaBiC5oWdtQN0tep2SK/Q0ggYScgo=", - "manifest.json": "sha256-uEJM2Pc5hRmaR+PpqU3brCfP2aRC/fB3Itfx59Sa2Q0=" + "manifest.json": "sha256-kkfJcn0e6R43oL/tjd9hRcF7872A/kCBClELBLWrJVQ=" } } }, @@ -21107,18 +21107,18 @@ "copy": { "directory": "copy/chart/", "files": { - "runtime/register/chart.js": "sha256-T98hQYpUxEQ3kRDeztnuOxP5XmwfddBBocBZ3rdTxT8=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/chart.js": "sha256-hVyc1MgrIwRQZWPz61YJX6ScFRhDJTjMKtYEs5Xtxoo=", - "runtime/chunks/display-Jm9bAsnb.js": "sha256-qZb1g04piEwY3lfFJwMe+0mXR218ljtVi8mepWxrFv8=", + "runtime/register/chart.js": "sha256-andwTROOZAuydVX/8AHv1ch78Vp2Bpfw0e1QhJuc1H8=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/chart.js": "sha256-b+gmdldG475mc83KqS69DHLQ3yWt0OTgOk+UNqB5J9o=", + "runtime/chunks/display-l54fb8vw.js": "sha256-xfzo614uMLlSbZc5l+o4vHvrL8yBjQAcV/HJdmPUJ/g=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-bZANhpWKREr2mT2bkDhKqg7tacAvTsBxyTk7F9aojeE=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Wk7EuPuisom2ohEBkZvcgafrpN7xXzlCUaNrWq7BZEA=", "index.html": "sha256-KOF9gaKfSWYWziOSnbA23zckGFW5yhlPXNWdth61Mc4=", "README.md": "sha256-AvM1lRutn7M/qWu0sIsbdBF9wn5nT5Ag8avrXpfo9a4=", - "manifest.json": "sha256-Or49KDdppCAKuoF2lIsC5y+XTd9Y4F5NIW2CvpmIBgE=" + "manifest.json": "sha256-Est3Gqn/L2c6gQ/ktXWGmG9Y2cwcaPVG7AIrl0KfXMA=" } } }, @@ -21385,18 +21385,18 @@ "copy": { "directory": "copy/kbd/", "files": { - "runtime/register/kbd.js": "sha256-92LQ/OR8FLn8svoWLL7M3e0cPXvFcgItaJ0rUFKh7E4=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/kbd.js": "sha256-lHOj6iq9s2QEMIGqbh8RGMmnU1sbrGNw4+mbuKuvByQ=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/kbd.js": "sha256-T5QaA4+IeB2lompHOT73eTmRDgi/JZa13mu/uFS6g5k=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/kbd.js": "sha256-sREzCvdvlM8nxOV76TpFGUozKTATyfoHLHd9BRIvups=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-BOKm1Tw9r1muXSVI33rhSJD46PIEFVs790GKSMxz6a8=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-tpH9QDJi6WP1xXEjkGhicB0miKDe2fe69wAALVp2X5A=", "index.html": "sha256-LueXjvAoEkpUVPKmWgpUPrXdj3mYXVoeh7xRosvVy1w=", "README.md": "sha256-CY2b+9Xug3mHZLhawZDvq8BFYG/fjfij5F7sNanjAy4=", - "manifest.json": "sha256-I1PrxYTqlOTc/bjc9Cqz3tX3S9MkTOKiKZfDj6GaoMU=" + "manifest.json": "sha256-zOCgbqlUAgYUqZiflWUJN8D3iREdCbe2uSNY7LTUVXc=" } } }, @@ -21848,18 +21848,18 @@ "copy": { "directory": "copy/alert/", "files": { - "runtime/register/alert.js": "sha256-tioVtq6u1i9xQuPnmdCiimbU19h1/epCn1uitDhU938=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/alert.js": "sha256-ipEjIR62L4Lq8O1vkv4IzvYM7kLeFjfhYEw6MSL03pY=", - "runtime/chunks/overlays-BwgpF4jI.js": "sha256-NAd99OT4kDsFp8IHscKRus2jY6XRsq+GMzplWbJsY4U=", + "runtime/register/alert.js": "sha256-7NCDMaMb7R+vWVYpL0Q7UOd/2hi0nNoG7b/xzw1ISwM=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/alert.js": "sha256-Ww7L88Sc1WN1nt7rRaqX4VZ6N9euzD/gg9otTIqd/24=", + "runtime/chunks/overlays-BW66WXLm.js": "sha256-Z9etmUpuDuykKbJkriLMz8iiYnOP9uMUAshKwoHc1I8=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-5Dd4DFZ5Lg+H5ZcZnWfb8Ommsp9rKKRLJYR0cpgWWpU=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-QUAq9dxIFB1jlxB27CrSrEZKRLa4rC6qRLbWmR2t/ug=", "index.html": "sha256-GQ2nYpJKuk1PCqh/falGa06i3ANZHhohF4LRN04wYwk=", "README.md": "sha256-tx+34leZRjiZARWtxlnmDc9/6JPBGKFZl1od0IYo4kc=", - "manifest.json": "sha256-WUBXZH3wEKDy2fuHpMItmwzDupMwJWkHiSFgo4bgJiY=" + "manifest.json": "sha256-InLGG3IWFONsGn5KCD24pSHkaUnfTaYX2B6SIBqEZpA=" } } }, @@ -22388,18 +22388,18 @@ "copy": { "directory": "copy/toast/", "files": { - "runtime/register/toast.js": "sha256-3boFTJqHNwJ4he43NpdsZK8ttLeqvz9HMoUtwFjVwtk=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/toast.js": "sha256-1dFBmSju1EG6JDJzOQqZ+RK4CzRzFpUX0heoc0jbyF8=", - "runtime/chunks/overlays-BwgpF4jI.js": "sha256-NAd99OT4kDsFp8IHscKRus2jY6XRsq+GMzplWbJsY4U=", + "runtime/register/toast.js": "sha256-T5DYWi24uZw+rG6LBmJOUq8W1SaQkxZXz7JNdRbEUfM=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/toast.js": "sha256-XsXKDN1g1p/dUFMGbcOZtPxqPsa1wVAqjrBDVX0e0jI=", + "runtime/chunks/overlays-BW66WXLm.js": "sha256-Z9etmUpuDuykKbJkriLMz8iiYnOP9uMUAshKwoHc1I8=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-uDOVAGMFD+o43PgFLYIr3brOp1t4nrDGrE8jaKF7S2U=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-2DXrOBOlEPzc9p3N5SEbw98qHHSMYTxlOnR6gT91kkU=", "index.html": "sha256-pfILKUsTjhG02CF143yBVB1w9s3PoEzh0CXq+YfLKdU=", "README.md": "sha256-Gqkqv+2L4+y8mTQfPGpUxoV4B+6QJazzN5XtXWfyj4w=", - "manifest.json": "sha256-nCmjWTAM9/Z9YpPdGU7WkaZ/5fph4teBlZgYWtPLSyk=" + "manifest.json": "sha256-oRSezqXzG8G2CO7SOE3gB8WFwPsFCgto2clZFaszucA=" } } }, @@ -22702,18 +22702,18 @@ "copy": { "directory": "copy/progress/", "files": { - "runtime/register/progress.js": "sha256-njMsMaNTGgxOBV8TIDHAQYyRI8+ERzh0jbkOW22fUzc=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/progress.js": "sha256-nQLxDlUaGyc+Y+OKp0jTGxlgHN79YT/NpaldZf1fxSY=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/progress.js": "sha256-544wDL2CKnD0+1v3NSxcLVzXp1+GIcKTRFrtYDC4bpE=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/progress.js": "sha256-ZEE/23ULhPm5c1MCkBDOl8/cfGhFjt3rCoBmtS07S4w=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-UwXFHO6OA2kZ3cHUZ8xWNx21ZB+espmS0o/GDj19Q4I=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Bm2XYmsDcMrSYl/yKw1emmfA++ea/EjE5wzSjdg0eyw=", "index.html": "sha256-eR6RiF/n8XvphWFe6R1Htt1DNndZuhW1zRV0M5wb1lM=", "README.md": "sha256-oXXC+n+f426Xr1+uHSEamfpzBwqmaBbe41P73puQ9p4=", - "manifest.json": "sha256-oWk8MNOarZ1Qp5bALfpqGLmKLM8MW7sRFrV1BhxRFJY=" + "manifest.json": "sha256-vbTBjyTT43/kBH3aGTWwenTTG+vpb/9uE3EwvrQyNH8=" } } }, @@ -23003,18 +23003,18 @@ "copy": { "directory": "copy/loading-indicator/", "files": { - "runtime/register/loading-indicator.js": "sha256-HHn/Y10+qdiLQ3DUo5i5OEHDhfg4ViJo8nI4ie7dJps=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/loading-indicator.js": "sha256-Z0q8XmSpQgrwC0AcFNlCQIZSt8tVvZ/ZF6McNG1rtBo=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/loading-indicator.js": "sha256-GksNrn8rJ9nRV9W+CbRKOa2vwUiQFLyqYpbcADyKm/I=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/loading-indicator.js": "sha256-1NsGiis031LwfMAwIj+8bNdvBPObvwdaJgoF3JXNGhg=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-ombtuuRs2PXpBfR+/B6paDohN3ODM1V0aNbRSzOcrmQ=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-yiCrGr/OXo7SakIH4qRV3wDHbj09EqyJ2F7eTQHbnbc=", "index.html": "sha256-2D4ozePauDWxVekXfRHx66zP4agX8tbRUgjo86Z3WjM=", "README.md": "sha256-YVFITjZXVN2sAQCTUcMZO5v0Xsc63owlmsQGMTQ42wY=", - "manifest.json": "sha256-Kt5NVgRUk7tSoXG5AttjyxsGM5maexW10LxUO1SCzVs=" + "manifest.json": "sha256-JBPrevY3vpaQ+G/AK4+vdQVCJgAibOXNADnnP2SzatQ=" } } }, @@ -23299,18 +23299,18 @@ "copy": { "directory": "copy/skeleton/", "files": { - "runtime/register/skeleton.js": "sha256-JdObZ43D4BCk7fNL7BZvz8hcDULGiVrwvC7nVz4lwFE=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/skeleton.js": "sha256-WSpVLmYkqKadgGqtEfd4Hma86gL9cG2QQC4FW0BXHKw=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", + "runtime/register/skeleton.js": "sha256-hbvs0AFMUUdqWlgc7sQW92NsxfPob/qt8wzn3y6gYTw=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/skeleton.js": "sha256-7goo0hT+UPHFncfxVWpEL6gxQb2ZyUWp08MM9rJHWWU=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-Fdg05sQx+/Q5Ia/CN1d6mo9ueZkpbJnBwTnVSbNePgA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-/g7jxryHfbaG3yxoxK8NfCh2k5U92wPPELD/107+2Ps=", "index.html": "sha256-fI+dNiKndtDjzLJEq6oahe+GPWudTAPb9j0TFGRIf78=", "README.md": "sha256-nzNnLPK+pu75MG+iTs+EMp/xOyJFTC/9GM9JCwIoCno=", - "manifest.json": "sha256-Ik0FL5m9q5FAvWWNRT6dgdhbRF/1wIv79I7cCsAlizQ=" + "manifest.json": "sha256-IDhTeG5MxLv+bexFNEe2Ppr6MRfjAq2SuWpDYogVv4U=" } } }, @@ -23669,18 +23669,18 @@ "copy": { "directory": "copy/tooltip/", "files": { - "runtime/register/tooltip.js": "sha256-G4uAYJmQJk4eTEhF1uHV44mtO+Vefw1Onc1nq3+iWlU=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/tooltip.js": "sha256-2j1hr66OBZli855FnMDI/StSj237p3llagSJpYZh1KU=", - "runtime/chunks/overlays-BwgpF4jI.js": "sha256-NAd99OT4kDsFp8IHscKRus2jY6XRsq+GMzplWbJsY4U=", + "runtime/register/tooltip.js": "sha256-F7E8JHr/JV4iZeeVJnARr64yUr2l01418fBM2UvligM=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/tooltip.js": "sha256-/JSDKAWa/JXNmAoOtDMptCVY8Pu5nChQ/4UK26P8KuU=", + "runtime/chunks/overlays-BW66WXLm.js": "sha256-Z9etmUpuDuykKbJkriLMz8iiYnOP9uMUAshKwoHc1I8=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-qYB8NrU6j0LSeluhANQt7hX4GwZJkfsCr7sElkRObAs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-+kSohyFbJg7z8/YUnlkzY1UQAu9ZLX7qE1eFLvk/1hI=", "index.html": "sha256-H8VqbExkj5zBn+UMGOUurqozbkho78wvT0O1LxdqEXs=", "README.md": "sha256-gCdLT45+37bldGYfH9LhZjTXGX04d3jZOS7ARTD3bCE=", - "manifest.json": "sha256-al7ShkhIUcTTbKc7gBOvzD1mJGDtWWgkwetbgUzoZI4=" + "manifest.json": "sha256-GgYaPJXmIXO4FHNDza+4NmU8dgYZlv7ixDUuG8GsKiU=" } } }, @@ -24243,18 +24243,18 @@ "copy": { "directory": "copy/popover/", "files": { - "runtime/register/popover.js": "sha256-NDvrOkPFLsVu6H7xsvbIrVzEyB991xTSx7kQeyplwJo=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/popover.js": "sha256-JHzjjn0Oz3mo6v5yPi+1LrMA+ii8LIIozp+09bAkaIs=", - "runtime/chunks/overlays-BwgpF4jI.js": "sha256-NAd99OT4kDsFp8IHscKRus2jY6XRsq+GMzplWbJsY4U=", + "runtime/register/popover.js": "sha256-xRkCFvW2ZZFE7oiyzjI0LU04ybC1vn0qsZSMwBHa0W4=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/popover.js": "sha256-AKogsKXEGlZ2TM7DbJBqt95rmp+cUmED/ovBHzwqPBA=", + "runtime/chunks/overlays-BW66WXLm.js": "sha256-Z9etmUpuDuykKbJkriLMz8iiYnOP9uMUAshKwoHc1I8=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-xmMasEZmjEVePt3EbtGTGv48RqUg6XWxZKYkmzUQlQY=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-tBbkSUEedfklBWmTm/lh13o3rlYHe/9AGgvmXp+p/Lo=", "index.html": "sha256-EXPyGAfu1NC/kmTVCftVrEr6TsOglaJBB5amGR0C4K0=", "README.md": "sha256-2w2CMw7jTANV0wE6ux5POoe9QeMf/7BVerq3YrpiziI=", - "manifest.json": "sha256-A9pCEvDbPktVmVfH8Cn5LqMZk46CJ4TwiSO3qu8sm4E=" + "manifest.json": "sha256-qtI7U9MQNcKuBJoWnGbTV5TN2koer6C1EJp9Vk8YHWg=" } } }, @@ -24960,18 +24960,18 @@ "copy": { "directory": "copy/dialog/", "files": { - "runtime/register/dialog.js": "sha256-waqEj5W9GRcvFu/OpnJxmONEY3yiBYgB2Fak5uwMsbA=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/dialog.js": "sha256-zdWNMLxqa07G4DrP8cSpEYY3F05kRGbx8cg0OGyNzbE=", - "runtime/chunks/overlays-BwgpF4jI.js": "sha256-NAd99OT4kDsFp8IHscKRus2jY6XRsq+GMzplWbJsY4U=", + "runtime/register/dialog.js": "sha256-JEbzrKsC4vP0ZdqSOolILA3NQuVhOa+XZoXfduM+PAI=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/dialog.js": "sha256-Bwsz1OfbAchVk6TFl8egez6a03B4iopAkl0edtrHcPs=", + "runtime/chunks/overlays-BW66WXLm.js": "sha256-Z9etmUpuDuykKbJkriLMz8iiYnOP9uMUAshKwoHc1I8=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-PL+Ntvoc1uooINO+TPwR7KzuU7dbER2pJdlz10y0UyY=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-wFFtRxUFWBTzxYOcblp+JjddYxJQF3QKoOb0/hIuSL0=", "index.html": "sha256-Q/j50VjcxyfFKNml07quAEQPOpf3g/BvIyvycnVJuzE=", "README.md": "sha256-qhTQOsunJthiAQNFRNPTJx74lX2dH6rh6jISELzgD5Q=", - "manifest.json": "sha256-K7i7iL46BCLXqiyFk9t8rU9BYhfn0lNPuOnIrHnuA5o=" + "manifest.json": "sha256-TSbiYeFvJMF2U6hGsE8nbaJyAV0b70JabFzXr6ix2rM=" } } }, @@ -25672,18 +25672,18 @@ "copy": { "directory": "copy/drawer/", "files": { - "runtime/register/drawer.js": "sha256-rA72wn/EhgwDqOffVBPLtBX9zTwVRgod2uadIlZcLe0=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/drawer.js": "sha256-1YuAUa33ScDJX74NBdYbrkllPWZ0abGZL2M1hnFJ7A8=", - "runtime/chunks/overlays-BwgpF4jI.js": "sha256-NAd99OT4kDsFp8IHscKRus2jY6XRsq+GMzplWbJsY4U=", + "runtime/register/drawer.js": "sha256-AM5iGLPnmhN77hlMQqOhJM8ZDYwV/jpxf4bjQDWLHlE=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/drawer.js": "sha256-xhVXm6IXbOoRG69KeKgXfir/YRSlIhTVtiygF1/uLwI=", + "runtime/chunks/overlays-BW66WXLm.js": "sha256-Z9etmUpuDuykKbJkriLMz8iiYnOP9uMUAshKwoHc1I8=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-r9vwT85nLqMxpyVzGQDrQIU3bpOdw5TleRvfLX3IVQs=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-RNAiKQJPioHCtfhMtqcsFaQFfwhKvdH+iIfLXOWo6QQ=", "index.html": "sha256-E0Z5esPR0fYfy04CP3TuZwrK6CEw4DIxyD9vXPSkZAI=", "README.md": "sha256-fOfwfTYC9vdlgQFOfWiigzqCKfrU93VWnGHVQW9kH8s=", - "manifest.json": "sha256-SyjiZGfW7kf4vufRk3oLDjiS7zw5VEwkSWdPMt7GjaI=" + "manifest.json": "sha256-yJbahCQlijj7/ZMLUN+3jSfKlLEZy5cgMCTZznnd7ok=" } } }, @@ -26258,18 +26258,18 @@ "copy": { "directory": "copy/empty-state/", "files": { - "runtime/register/empty-state.js": "sha256-O+XPQiZJD3SM6EGCJ9p7Ia3RwHie8uDXVlJd2Vl8f1g=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/empty-state.js": "sha256-+Vgad2O/oKiGnSsGD63zlNKxCzqpHWhZ85dwct4yBx8=", - "runtime/chunks/overlays-BwgpF4jI.js": "sha256-NAd99OT4kDsFp8IHscKRus2jY6XRsq+GMzplWbJsY4U=", + "runtime/register/empty-state.js": "sha256-dB0amDn9V/in58Egc89rJ/1PCddeEm7h/pF3stAKhXo=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/empty-state.js": "sha256-4YkbuqMtIaxwQuQSzV4W2x18ZCoezW1TwANoDpPK3aQ=", + "runtime/chunks/overlays-BW66WXLm.js": "sha256-Z9etmUpuDuykKbJkriLMz8iiYnOP9uMUAshKwoHc1I8=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-BeQzoBMmZ//SCPym1JhwPfMM51a6wiO3oVtwH7lOOpc=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-j6rKuP4LmxmaKm47ZcfAqQ0LKMqN7l90HZwvUydHutQ=", "index.html": "sha256-stJ7LYfCGn32eDmo6PzwFlZwtF8GlPwt4gCAQ4f6EfU=", "README.md": "sha256-460PP03z7gtyCcQW1opIbUBVyz/wg3Dv8SyzbynmB2E=", - "manifest.json": "sha256-ubp6C9NL9OCyq6QLT556NHrWxWfehrZJwTjOfOkr4wU=" + "manifest.json": "sha256-cvIfK+Ds7EzrT7+nTFN0wNCb/+G0YJLKPKgfySV/7CI=" } } }, @@ -26825,18 +26825,18 @@ "copy": { "directory": "copy/error-state/", "files": { - "runtime/register/error-state.js": "sha256-7HAfC906Fv50aD7dtTHvGX8XoxDanaS7Xy+pD6+6JlQ=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/error-state.js": "sha256-BhughrbljbgIQKlE3iHBAZ5sfaZgHxDG49Pr3eO+qEA=", - "runtime/chunks/overlays-BwgpF4jI.js": "sha256-NAd99OT4kDsFp8IHscKRus2jY6XRsq+GMzplWbJsY4U=", + "runtime/register/error-state.js": "sha256-aJDvxh9+vUwd9iM93dBzHIYNHsvxbRWb+PWyrx/cUME=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/error-state.js": "sha256-oighlDczb4A0AuMh+nzeDiwSkUzdI1QF8Cq/NbkPlcs=", + "runtime/chunks/overlays-BW66WXLm.js": "sha256-Z9etmUpuDuykKbJkriLMz8iiYnOP9uMUAshKwoHc1I8=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-PkulOjRkq7PLGjfU346e4I1xzJqOFRjr9UgXNeugJLY=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-ORjrriOpBHk2VlqSsyeUSEs1medDwB5oaTT4RxrXLFs=", "index.html": "sha256-oKMXjqXWa3C9B3nx3LWjOjaPYvvFEL4y4yUPyCiyHFI=", "README.md": "sha256-Dl3lNTMlz4fye9SN1UJc6WVgA6BbWKgqHMIRpH62yOY=", - "manifest.json": "sha256-pZSXraMAM3LPuhv/6n3+7FR5RxqyhkPxwUX/iFdIWSM=" + "manifest.json": "sha256-JVn20IIGWKkLSG9VQVc1nUrIgYpvJMLvi5nFiu2hg50=" } } }, @@ -27375,18 +27375,18 @@ "copy": { "directory": "copy/code-editor/", "files": { - "runtime/register/code-editor.js": "sha256-qnN0iH+h4BDWCcc4Q3/6f1t7opIG5ze5nI1wsQL/tDg=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/code-editor.js": "sha256-MMz8rm+dJT4XahXmR9ftmU0IhNW1NqLIHW7U3STXDPQ=", - "runtime/chunks/display-Jm9bAsnb.js": "sha256-qZb1g04piEwY3lfFJwMe+0mXR218ljtVi8mepWxrFv8=", + "runtime/register/code-editor.js": "sha256-UdHVDO1voHkuJxvk2L6GqXlhe33V2vQjMWxXPn1khuw=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/code-editor.js": "sha256-cSXmUpi0vGMqGobq9++3IbvncnACcWtOqxek0flaVgs=", + "runtime/chunks/display-l54fb8vw.js": "sha256-xfzo614uMLlSbZc5l+o4vHvrL8yBjQAcV/HJdmPUJ/g=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-aa9zAzIlna+IPd+Xivi0WU385o/+RmhG5pRVR1vsE64=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-yXGoyQ6QC1zx9v7pXmaH1J2StJS/EEc6ZMqWAgdNj6A=", "index.html": "sha256-2pHlO7mTG0Z1FySFL7jnRFIidQEfcMXdM+OtJBsZeXA=", "README.md": "sha256-oP4WnaIDAzxwm22ndFvMgchWr7l/DH7YotacPAFZuO8=", - "manifest.json": "sha256-OINO1eXNSuTLSRe6ibFtS+KeQIlXQmszvJpDmyx0/xs=" + "manifest.json": "sha256-zLyZ3TTrERwSfzkV2jv+eEH2zYN8S67pbrLxiPokZ8g=" } } }, @@ -27970,18 +27970,18 @@ "copy": { "directory": "copy/editor-search/", "files": { - "runtime/register/editor-search.js": "sha256-R0CYRlMKJW24RObuaWNYkCNShO/Qtkkh/n9CWJ33FFA=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/editor-search.js": "sha256-aUfiB2u6bRwR1VhsFjANGyo6S0HHuA5lveVDShHVo3c=", - "runtime/chunks/display-Jm9bAsnb.js": "sha256-qZb1g04piEwY3lfFJwMe+0mXR218ljtVi8mepWxrFv8=", + "runtime/register/editor-search.js": "sha256-41yygigjUcGOY69CxJZW+uJFV1ZwXq+Kq/S1Hyh7G8E=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/editor-search.js": "sha256-d2zlER1T0jNTiSDF+a92FN6Tb5wzooCYr1ETcBEY+wc=", + "runtime/chunks/display-l54fb8vw.js": "sha256-xfzo614uMLlSbZc5l+o4vHvrL8yBjQAcV/HJdmPUJ/g=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-EsEJrsGIZ88TEP4pXc0Jt3WQxhCysigIkd1ddeNbHBM=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-d4aAYzdcDHNmdiry3w1Y3xEHMEA6MELYHpoj25fZY7M=", "index.html": "sha256-f7NqN883Z+7eUEbHFc9OPrlTwgcg/uxCcMTJm7xVNZ0=", "README.md": "sha256-uCiQ7xpaMDEYDoL/7zMcafsbXKeQ+tnAyLmxgCMABh8=", - "manifest.json": "sha256-1TxEf5DD4kNTVifj65tU5NzGDOhBTser7acFaOPlY+Y=" + "manifest.json": "sha256-A06+dBDdDT2cYEvZUmajvJpMDPBzS4T26NYL7uorb0s=" } } }, @@ -28546,18 +28546,18 @@ "copy": { "directory": "copy/diagnostics/", "files": { - "runtime/register/diagnostics.js": "sha256-ALvK2a/RKv8dPsd7vtPOz2gs07sAqHYUeaLkBGbL2bQ=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/diagnostics.js": "sha256-oEE2P+tyCuYFS8Z67kakU24ozr9nPJsXvN7ug/nsESs=", - "runtime/chunks/display-Jm9bAsnb.js": "sha256-qZb1g04piEwY3lfFJwMe+0mXR218ljtVi8mepWxrFv8=", + "runtime/register/diagnostics.js": "sha256-hjSy+H8Mj1uBgwhB3c/KjtBkY7xJnYXTSeLGJM0xvdU=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/diagnostics.js": "sha256-QBQTzBXbzspprSZunB6lifyi7iGa8PykXE4Qvmdc+mI=", + "runtime/chunks/display-l54fb8vw.js": "sha256-xfzo614uMLlSbZc5l+o4vHvrL8yBjQAcV/HJdmPUJ/g=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-xWB/G9X0gadCbFJ8yqKBaXbBvMPSKyKrVUQR4dZZs88=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-oPPp/R+dnwC1tnH/Td+Hlrs3CRODUkA4Bvq/HK/fAUU=", "index.html": "sha256-faTuPIwIaIe118O39CQtFz4nACEFH1MOeuPsBOwpHh0=", "README.md": "sha256-zoebnEYS306DsFzwTsEnc2EoKA+8Dm/eyz4eTXdSnAs=", - "manifest.json": "sha256-/tKvGRBc6hhqnfZJ7dYirqMb358NCxUY8e4KhG4y9j0=" + "manifest.json": "sha256-gGsegK/zB/UXWJ1b0OAHgz/8LfomuJdrZMd2N7SuRNg=" } } }, @@ -29068,18 +29068,18 @@ "copy": { "directory": "copy/diff-view/", "files": { - "runtime/register/diff-view.js": "sha256-9TubYFM9ksBHugPVTEwpyuq1pqPeA3BwnBpoJdM5zRE=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/diff-view.js": "sha256-mc+zZLXtFDZnF4okQ840vLAw4mC40kkmR920bUXfXfo=", - "runtime/chunks/display-Jm9bAsnb.js": "sha256-qZb1g04piEwY3lfFJwMe+0mXR218ljtVi8mepWxrFv8=", + "runtime/register/diff-view.js": "sha256-BsyD+ZpxaLT5ZiaNNhFmNuMdqFMWiOTd9cR6DViCLm0=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/diff-view.js": "sha256-ZypShgLxT+vpLJpO7zGyps5bBAEEyS3zxyCDCxJvz+I=", + "runtime/chunks/display-l54fb8vw.js": "sha256-xfzo614uMLlSbZc5l+o4vHvrL8yBjQAcV/HJdmPUJ/g=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-zQ+2X33S+1rlKgj8VvnNJSfS/ujlxlYAFFAC3vC+8MU=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-t7cx4Y+4qhIPiwFbRPz+6U12N/CFATPTfG7/iZf85zs=", "index.html": "sha256-qm8fbs91KUEOm2ss0XShYkbQLzgXVk9OpdrVHfg6Wjg=", "README.md": "sha256-2/6IFU4JJZ25X3ZvCCwHM1P9pvt3nJHAUfxoS/Ubi/0=", - "manifest.json": "sha256-9Y803JsNKTzO9FZrSrjpWhyIAFnC0ZGfnQWxqX0Mz/w=" + "manifest.json": "sha256-umOsaI8V2Tt1tM7OwzbtZlpPW29lyWQpQU3vyS01Adg=" } } }, @@ -29612,18 +29612,18 @@ "copy": { "directory": "copy/terminal/", "files": { - "runtime/register/terminal.js": "sha256-DtAEqikNcqq/nXccSq0pFsKXxE0BPFgM8N6lScud0Ic=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/terminal.js": "sha256-LBmUT0u6uCLNgKHb3qON4Yl1HjbBCYOByCIC8bGXv2c=", - "runtime/chunks/display-Jm9bAsnb.js": "sha256-qZb1g04piEwY3lfFJwMe+0mXR218ljtVi8mepWxrFv8=", + "runtime/register/terminal.js": "sha256-cqkzu0k247NODxqCLXUjAjT5HVFF/pB9v/cPjdOuIzU=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/terminal.js": "sha256-8gdvRHMk+UXDGa4oKnrV2VH510F4JOGMzVBX9w+nw0E=", + "runtime/chunks/display-l54fb8vw.js": "sha256-xfzo614uMLlSbZc5l+o4vHvrL8yBjQAcV/HJdmPUJ/g=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-qVvYtOU0V9tpTXLiTfobfn2Bv+Ec58ZxsvFuoOO3zqA=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-WyXNyoxiAXNq3bLZRmrc1qS2XzgHghN+5tO+9HpocVA=", "index.html": "sha256-u2hUMomyNUZvWxfeRu+YXJNwoBZRQAU9c+Wlnmdt/uc=", "README.md": "sha256-JMb0MyBFXbZ2TBIQrpRDNUjcH0R6qtmsRDfzwcOAY6o=", - "manifest.json": "sha256-R6fteNdTjGjYY6RLBBUjM7wUCoxN1QCxe7DGXnqO9Yg=" + "manifest.json": "sha256-E9cWmkLUFpaqgEbSE1Ee1XeECG37AHYy2D3MGUli1hM=" } } }, @@ -30450,21 +30450,21 @@ "copy": { "directory": "copy/settings-panel/", "files": { - "runtime/register/settings-panel.js": "sha256-Ob0kL9R4vmbYJ7EqPNT3788vg2FpTs87xAsE1TbqHeg=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/register/switch.js": "sha256-6l7gxY7bHWXI4K8WMdikGfg6Itnf2Uy8hSbsvn+XCYM=", - "runtime/components/switch.js": "sha256-sdfSvJlKylAeDbhRKPMRUZ+piEOzKs1aV52BDvjOV/o=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", - "runtime/components/settings-panel.js": "sha256-2/vcKktPpt7/9RBfexqEoFAPjNDcISoi6AALg6/CVTw=", - "runtime/chunks/forms-CE_hP1hg.js": "sha256-uOnoMuSkUbm9C/GfR+PDLYCykyHOQ1Ni7g59c4YMOS0=", + "runtime/register/settings-panel.js": "sha256-9rj2m46hgJMosP85Z0xhOpSLAAL4iBWxUQVTwTmueq8=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/register/switch.js": "sha256-DuUxpd3L4nKgHvyJPWJ+2TZBOWxcTy0MOtxrbgEWF/I=", + "runtime/components/switch.js": "sha256-CVbrKOXLXh5ZRJ7UrRkrE+VgZ8zGcaD6GE1mYPPDdio=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", + "runtime/components/settings-panel.js": "sha256-XmcGNm6lxEdrb/RfdzNnk9NhOsMTTxK3Dv437FczSgY=", + "runtime/chunks/forms-C3u5121t.js": "sha256-DymhKeiaCcQj+DmkDxoEwP0Md4YxiSpCxyYS4eiMnV0=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-k+UkB8smqd63SQIr7NXfAoXvhCZooblbGmEzkIW0mz0=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-Z1ZqDdIXySN8gWG0bvhT8iMaa+GaOyHy/vumYpCsYt8=", "index.html": "sha256-o83BpK03vkko3vqQPfArOayVjD634LtFPrmdQbjqbQ8=", "README.md": "sha256-Jbd8VDlivmCdwjmixGLdZrE/QQ9xdJyk+UIIOcLDqZE=", - "manifest.json": "sha256-UqEXYpbq1ptJHggPNTUN19vUEvRV/ELMtZcfaM70e4M=" + "manifest.json": "sha256-uu9pq63FfqBIHGu9L2UB67aS2FGsLS8VDmMAN4aCJ2c=" } } }, @@ -31383,25 +31383,25 @@ "copy": { "directory": "copy/admin-form/", "files": { - "runtime/register/admin-form.js": "sha256-3IJTJLTksVuLj5PxdfQUbymfAb+K4yKLDzOUMb+MHP0=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/register/text-field.js": "sha256-gmqyzVDUD/VCnOF5nDRA0n1F4I7q7lE02AdZeBCFrUk=", - "runtime/components/text-field.js": "sha256-4c47ee0iFW2YWW+dVR1PBSJMwOOa5rmKhJSalXzm+Zo=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", - "runtime/register/textarea.js": "sha256-OGjZrk++zzTI91HXv7chKm86kRb5xICVcoOOdMidF2g=", - "runtime/components/textarea.js": "sha256-pi3Oj4itdBVYU/EaRSZ64BqAEsBdeUH4LCG2kwSUKfw=", - "runtime/register/select.js": "sha256-TN7apnaEDR69Eobpnesx4c3Yr2iU33xNGj/q9i+nFtw=", - "runtime/components/select.js": "sha256-QSO5F4fiwtnnIHZ9/a9n62yVZRlGUIofNkw2oXYIzGY=", - "runtime/components/admin-form.js": "sha256-FVzHg1y71Fg3LptLCSedTH/NQIxijxfYfjfBaYWXGS4=", - "runtime/chunks/forms-CE_hP1hg.js": "sha256-uOnoMuSkUbm9C/GfR+PDLYCykyHOQ1Ni7g59c4YMOS0=", + "runtime/register/admin-form.js": "sha256-yYy1AQy9AAay2N03Zg4YG6XoNz4WvuslU9TQ3hVosd0=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/register/text-field.js": "sha256-MdEo5+b/G/mM5hz7fcSDyO//Htiapsit78fIYEhm59k=", + "runtime/components/text-field.js": "sha256-qPB+cDkHzpm0/dIb3MLq2aw8aYuTw8eeiXDYfuaVwwE=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", + "runtime/register/textarea.js": "sha256-kKiC3PacJzn+IIdz6JEkzMEOawMA3/ge/FCAnqsmWPM=", + "runtime/components/textarea.js": "sha256-/Z89vI8KLV9ojTcxZPRnV0C0nGRVDX3vFp0LRy/BR4M=", + "runtime/register/select.js": "sha256-a/ebYoMxXf0lulroJxRYiTUDtJLmr23xOp4f3nhwepc=", + "runtime/components/select.js": "sha256-5I3s1W7GlcelP7ffSDNZXafcFZmzILO7gFZrwhZh9Ps=", + "runtime/components/admin-form.js": "sha256-nyvONORv1EfGlW/M4O9Ee7xfMtIOTsqlYyyIWgOF+yg=", + "runtime/chunks/forms-C3u5121t.js": "sha256-DymhKeiaCcQj+DmkDxoEwP0Md4YxiSpCxyYS4eiMnV0=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-N8dnCpPJJWG/StUZN68/NzU+Ag/vEyCPsjoHNJ8SMTI=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-TRLraonRxggrZcfXS9jlN+nTIOpRHiXbMKQNm8NbR2A=", "index.html": "sha256-fCyv1GPEoas5phPBo4T3EhrTQ5U3/15ks0AZJQawjDc=", "README.md": "sha256-bid+/EA6npftuo0cAZQP6rg+96qu7gNC4h/Klx23PF0=", - "manifest.json": "sha256-qLocGmsNdOM4Kxf0Fo73ND/8SXaknuN2y2Z2ZwG/FL0=" + "manifest.json": "sha256-CZpsDr9vBVqJHzKFBNQ1rV6Hp2i7SX0FCfV36645rM0=" } } }, @@ -32152,21 +32152,21 @@ "copy": { "directory": "copy/filterable-table/", "files": { - "runtime/register/filterable-table.js": "sha256-14GtCkn2rDEs/16Zp9P3ejF4+WJRKBEjPP8iHA/QieY=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/register/search-field.js": "sha256-oIExIQ80Xzt1d5Y8KclVl+lAi+cgOMhKMFNPBz8fEXY=", - "runtime/components/search-field.js": "sha256-HCnoLO1ZZvDEqeON+Ir7Q+XChuArNr/tJ7H+lnVTJPw=", - "runtime/chunks/native-BjBt1sUh.js": "sha256-UbG+1dCvUgpK1/vnx2xDtwwcG1dueRiV1iBEEt9oP7s=", - "runtime/components/filterable-table.js": "sha256-xbo/MykYle7VwG4ArKqnOAwxD6bA5BruTf9Mi33CxnE=", - "runtime/chunks/tables-Cjr1EIJz.js": "sha256-K6BF6M6xNawgWdL+NIcBRZmY98j45o69tBI034Ks4Bg=", + "runtime/register/filterable-table.js": "sha256-lPgjDjZWOIpHRh1cQ/CLEze3gvrrHq2LenxoIZiYwoo=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/register/search-field.js": "sha256-6LYU8HU+rH1uC262cp+QTcMOL1fOJadTf2sVIOar7yw=", + "runtime/components/search-field.js": "sha256-DR2wccoQwBDsamOMrOnUSaYWdhk+1zRdrnB9VfaIthY=", + "runtime/chunks/native-D61761VL.js": "sha256-OpLgNJ3+fyz2fjrs+MXXNkgIZfOW56wVOJ3ZbguLteE=", + "runtime/components/filterable-table.js": "sha256-WhFAB4Ycphp6+E956qxhLre3L3oejvNcC1NGSNJrqHo=", + "runtime/chunks/tables-zo8ebTOo.js": "sha256-+LRPZmFKPk0oe8q3HDlfXCXkloBbkRbiFHVHczc3GEs=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-yuQ4f52VMqzL7ZWwuc/Ln3tYKuwWDma8x9yxx29wwLg=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-3PbF9wWtnKy3q07M9x690D730biEbSwu20wHAcvPPEE=", "index.html": "sha256-L9dRgFL5Tl9EFw9DuTPQaPstK4H0R/A/bzroaL7tvHk=", "README.md": "sha256-eYSWLSbTgjyr+5CUJR+E3qhY267Qh6rmF+5P40UanuU=", - "manifest.json": "sha256-241aHbTVmM2Zm6n7I+iXIVUlp/cFG7Sms6dBmoCL5w0=" + "manifest.json": "sha256-Oq9HQCEheDtWrjOzkY+U+/553gCyB/7XmxCgqbsWQUs=" } } }, @@ -33117,19 +33117,19 @@ "copy": { "directory": "copy/i3-window-frame/", "files": { - "runtime/register/i3-window-frame.js": "sha256-qJqHg9H/tx8mSRirpY3qYPpAbM/tk7akOF7Sb6yIBVw=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/components/i3-window-frame.js": "sha256-Xeo48w2qLhBiwCVHaA6whyxItZy/aAj1xHVCQHHnGhk=", - "runtime/chunks/compositions-D57dCsBz.js": "sha256-PEpI/vGgdD+LSznUd0iedSxxVE+5QxIO7BGKeQnCRjo=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", + "runtime/register/i3-window-frame.js": "sha256-Ov3rofs1avoZR0C4IqqkijLrojDAHlDuk7wor1rg70Q=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/components/i3-window-frame.js": "sha256-gKjEbi3JtUqHZR58RGIkZhx3LV31jTM0QacXjNxKLLE=", + "runtime/chunks/compositions-DWG4tv9E.js": "sha256-vV/UcQrj3UFpVXymFuH4t/h/T+7JqBeND9xuyVdCjqo=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-j6gn6V0mtTIbd0cJHobuNavfKnCi+dJ0Xg8IoZdHp/U=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-r16RBHw/9BhmfwHsOtPnFIkDRIuIAmlN+RpR9z4LXMU=", "index.html": "sha256-vsi84+uGu4rv5NlM/V/to85JQlSDYVg0XKREuwBARII=", "README.md": "sha256-C0hpJoSU0W6E5VFxM/5nRjno1clSop0NLti9ZjvJiO0=", - "manifest.json": "sha256-NCADJPP+EWUI8DZnW9R3SkOJAG8+IaNI0Y87CUVua5o=" + "manifest.json": "sha256-XQqsgeYYQ9LXW/gihUnf4A3BL00Udvz3KBTba8gbTqA=" } } }, @@ -33762,23 +33762,23 @@ "copy": { "directory": "copy/file-browser/", "files": { - "runtime/register/file-browser.js": "sha256-6aZxofgHXmaSyrN62aRqrgBNsgXkVl76hwSUGwzsxpM=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/register/tree.js": "sha256-5FC2B/6Dr2k5l/nTb9KKizslYbXmQxe2nEoLuYG6zDg=", - "runtime/components/tree.js": "sha256-mYl4DYRuChSjXkRwM7LaJ31aYQZlvzP0RgTYmuNdC9U=", - "runtime/chunks/advanced-CqBF0dSb.js": "sha256-ozOzkRU6IeVGBqU3XQ0aLledkAi9vcs8dJdMQutVevs=", - "runtime/chunks/markup-DeQ4bEMR.js": "sha256-Eyyx7MKBoqXK4i2HaVUQhKUM066L2wIggABt6jAdgas=", - "runtime/components/file-browser.js": "sha256-rX/Iibk2FD9zA2T7ojRVZgvx3P/v8vt8GOi0X/OOEOY=", - "runtime/chunks/compositions-D57dCsBz.js": "sha256-PEpI/vGgdD+LSznUd0iedSxxVE+5QxIO7BGKeQnCRjo=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", + "runtime/register/file-browser.js": "sha256-JGPbb5bwIfA5k1lkGmAD5MHW7FaEf/ACtTM2u/vPPbo=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/register/tree.js": "sha256-GkpgoR9dpb/ho4x6diQOMGUvBv63XZ0KfaibFjm74gA=", + "runtime/components/tree.js": "sha256-P+63dC5MB2gKl/raxboRMQBCkbmDE850SXCmGt09e/o=", + "runtime/chunks/advanced-BrFnVc0y.js": "sha256-FVberBpKO49P/WGnxa61BTxhYsLnnvMFInur/TwjG44=", + "runtime/chunks/markup-AopKpwOF.js": "sha256-/Dn3cWEmlRQzeQAPVf+C0AooVb1pdIQeNeqd1fQVoPc=", + "runtime/components/file-browser.js": "sha256-f7EdtKJccQxuUuP+3ZqlKg9dJhLkwcMrO9wF55ABqtU=", + "runtime/chunks/compositions-DWG4tv9E.js": "sha256-vV/UcQrj3UFpVXymFuH4t/h/T+7JqBeND9xuyVdCjqo=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-UxawfUHhz140JTldQCb8aDbVaLGRxrgbxNCkmCkXxmM=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-TbSmPr7cV31g3WqgPi6LboOGQdmgxz/89Tf/3ld2pfU=", "index.html": "sha256-ghy6Hidly07DbSb9oIl+42dgKaIRi5V0gVlW8uwsoYs=", "README.md": "sha256-pldg7PuzlPHL6J8L3tFRBhM4Mqi8AlcED3V2DXOXZRU=", - "manifest.json": "sha256-7lqHULQBVMHEaRp9C8gbDNfM8EG6QEtHgdKA45i3mKM=" + "manifest.json": "sha256-MFkY0L5JDWoFk1lcMG7lcv7LxWhxgiGTofrx8pVTIIo=" } } }, @@ -34437,22 +34437,22 @@ "copy": { "directory": "copy/compact-dashboard/", "files": { - "runtime/register/compact-dashboard.js": "sha256-hCoso+VES7vbCkeradjbcmoYaD/A7Zk2HcIGKzkkT1k=", - "runtime/chunks/element-Dovcr9Ky.js": "sha256-7tXEQrcJPBXSDlmCqor6zZVtsFMvL54mFXd6XSTVzQA=", - "runtime/chunks/choice-B7mo5Eq3.js": "sha256-hACG+H+nHbUf/wRpyOCQ5RYMwxhd/Fiv+PtEWm0+Bkc=", - "runtime/register/chart.js": "sha256-T98hQYpUxEQ3kRDeztnuOxP5XmwfddBBocBZ3rdTxT8=", - "runtime/components/chart.js": "sha256-hVyc1MgrIwRQZWPz61YJX6ScFRhDJTjMKtYEs5Xtxoo=", - "runtime/chunks/display-Jm9bAsnb.js": "sha256-qZb1g04piEwY3lfFJwMe+0mXR218ljtVi8mepWxrFv8=", - "runtime/components/compact-dashboard.js": "sha256-Y2R2ASCxDuMVCbBdUqOGP60JpwtPCK17jCjpQXz1hhE=", - "runtime/chunks/compositions-D57dCsBz.js": "sha256-PEpI/vGgdD+LSznUd0iedSxxVE+5QxIO7BGKeQnCRjo=", - "runtime/chunks/navigation-BfNzDYZB.js": "sha256-OhGJWNOz3aZxPAacBgEhAFmBLRt/BGPr7INBjumqyQo=", + "runtime/register/compact-dashboard.js": "sha256-P8HNsRbiUifDMRZHPW2MbhfKm+dn03BeYVKCHO8pd5A=", + "runtime/chunks/element-DcrNU9Wh.js": "sha256-K12Hi4AEpZEosnfTD6MzmDSw+hv7REmmrIycBycQhpY=", + "runtime/chunks/choice-DqwWT5pJ.js": "sha256-PO0KJ2PRfy2FN9q9+VSvDnxi1skgfEZswjJnJcZIakA=", + "runtime/register/chart.js": "sha256-andwTROOZAuydVX/8AHv1ch78Vp2Bpfw0e1QhJuc1H8=", + "runtime/components/chart.js": "sha256-b+gmdldG475mc83KqS69DHLQ3yWt0OTgOk+UNqB5J9o=", + "runtime/chunks/display-l54fb8vw.js": "sha256-xfzo614uMLlSbZc5l+o4vHvrL8yBjQAcV/HJdmPUJ/g=", + "runtime/components/compact-dashboard.js": "sha256-YBUDjeM+Qi1QpjrdGLeWThioY1qC2/SilmX5Le+aUpA=", + "runtime/chunks/compositions-DWG4tv9E.js": "sha256-vV/UcQrj3UFpVXymFuH4t/h/T+7JqBeND9xuyVdCjqo=", + "runtime/chunks/navigation-CknoksQ5.js": "sha256-4yNcpxqrLbnNx8CaY3mnoMiZLbQunC4AzkuhPHWjVwM=", "tokens.css": "sha256-7HNUwUO0RfX8jPMvp0gqL5lcjjTDPlhJGzs8j7seouU=", "component.css": "sha256-7CRIHJNTDt06T3ztva5EpY4ytKr+vSsMZHxxolQ/+GU=", "LICENSE.md": "sha256-qIhhY3s7J0Mo6RsjJ0tLGwDZv4hHq8knuhm+YGjpzh0=", "element.html": "sha256-I++zY2714BqcfCh02WgcXCFwujrwXLK4TwP9wII+QE4=", "index.html": "sha256-jCDMPy0iYNKdA2sWCK1pFAeKyhEr/jK4IN0ias0Drlc=", "README.md": "sha256-6g2tbWoWmdPy5ju9eAR0VdQ5vp0GjEEftnqhmjoP1j4=", - "manifest.json": "sha256-jRq9uUQPaE37uiQUdKCVIiu16eHtJBqT2iZWAa/5iQQ=" + "manifest.json": "sha256-NNCsh/fxXpIMYEIuWrUTU92MV0xi/Q8eV8i9hhkDveo=" } } } diff --git a/packages/ui/dist/register/admin-form.js b/packages/ui/dist/register/admin-form.js index a6ac994bb..3dccd51be 100644 --- a/packages/ui/dist/register/admin-form.js +++ b/packages/ui/dist/register/admin-form.js @@ -1,9 +1,8 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import "./text-field.js"; import "./textarea.js"; import "./select.js"; import { J3w1AdminForm } from "../components/admin-form.js"; -//#region .cache/ui-build/entries/register/admin-form.js +// .cache/ui-build/entries/register/admin-form.js var element = registerElement("j3w1-admin-form", J3w1AdminForm); -//#endregion export { element }; diff --git a/packages/ui/dist/register/alert.js b/packages/ui/dist/register/alert.js index 4398942dd..eaf0f2a76 100644 --- a/packages/ui/dist/register/alert.js +++ b/packages/ui/dist/register/alert.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Alert } from "../components/alert.js"; -//#region .cache/ui-build/entries/register/alert.js +// .cache/ui-build/entries/register/alert.js var element = registerElement("j3w1-alert", J3w1Alert); -//#endregion export { element }; diff --git a/packages/ui/dist/register/avatar.js b/packages/ui/dist/register/avatar.js index 9367113f3..1a0c3257d 100644 --- a/packages/ui/dist/register/avatar.js +++ b/packages/ui/dist/register/avatar.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Avatar } from "../components/avatar.js"; -//#region .cache/ui-build/entries/register/avatar.js +// .cache/ui-build/entries/register/avatar.js var element = registerElement("j3w1-avatar", J3w1Avatar); -//#endregion export { element }; diff --git a/packages/ui/dist/register/badge.js b/packages/ui/dist/register/badge.js index 2fe7fff68..574a2903e 100644 --- a/packages/ui/dist/register/badge.js +++ b/packages/ui/dist/register/badge.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Badge } from "../components/badge.js"; -//#region .cache/ui-build/entries/register/badge.js +// .cache/ui-build/entries/register/badge.js var element = registerElement("j3w1-badge", J3w1Badge); -//#endregion export { element }; diff --git a/packages/ui/dist/register/breadcrumbs.js b/packages/ui/dist/register/breadcrumbs.js index 1b41f187d..2f3205758 100644 --- a/packages/ui/dist/register/breadcrumbs.js +++ b/packages/ui/dist/register/breadcrumbs.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Breadcrumbs } from "../components/breadcrumbs.js"; -//#region .cache/ui-build/entries/register/breadcrumbs.js +// .cache/ui-build/entries/register/breadcrumbs.js var element = registerElement("j3w1-breadcrumbs", J3w1Breadcrumbs); -//#endregion export { element }; diff --git a/packages/ui/dist/register/button-group.js b/packages/ui/dist/register/button-group.js index 86bb9c765..48b52b1c6 100644 --- a/packages/ui/dist/register/button-group.js +++ b/packages/ui/dist/register/button-group.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1ButtonGroup } from "../components/button-group.js"; -//#region .cache/ui-build/entries/register/button-group.js +// .cache/ui-build/entries/register/button-group.js var element = registerElement("j3w1-button-group", J3w1ButtonGroup); -//#endregion export { element }; diff --git a/packages/ui/dist/register/button.js b/packages/ui/dist/register/button.js index b01aa4dae..bc7ea515c 100644 --- a/packages/ui/dist/register/button.js +++ b/packages/ui/dist/register/button.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Button } from "../components/button.js"; -//#region .cache/ui-build/entries/register/button.js +// .cache/ui-build/entries/register/button.js var element = registerElement("j3w1-button", J3w1Button); -//#endregion export { element }; diff --git a/packages/ui/dist/register/card.js b/packages/ui/dist/register/card.js index 2a9535cee..2fd6ddbba 100644 --- a/packages/ui/dist/register/card.js +++ b/packages/ui/dist/register/card.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Card } from "../components/card.js"; -//#region .cache/ui-build/entries/register/card.js +// .cache/ui-build/entries/register/card.js var element = registerElement("j3w1-card", J3w1Card); -//#endregion export { element }; diff --git a/packages/ui/dist/register/chart.js b/packages/ui/dist/register/chart.js index 8efbe0a3f..e1c79eef1 100644 --- a/packages/ui/dist/register/chart.js +++ b/packages/ui/dist/register/chart.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Chart } from "../components/chart.js"; -//#region .cache/ui-build/entries/register/chart.js +// .cache/ui-build/entries/register/chart.js var element = registerElement("j3w1-chart", J3w1Chart); -//#endregion export { element }; diff --git a/packages/ui/dist/register/checkbox.js b/packages/ui/dist/register/checkbox.js index 70632e2d0..c03d18e2e 100644 --- a/packages/ui/dist/register/checkbox.js +++ b/packages/ui/dist/register/checkbox.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Checkbox } from "../components/checkbox.js"; -//#region .cache/ui-build/entries/register/checkbox.js +// .cache/ui-build/entries/register/checkbox.js var element = registerElement("j3w1-checkbox", J3w1Checkbox); -//#endregion export { element }; diff --git a/packages/ui/dist/register/chip.js b/packages/ui/dist/register/chip.js index d6b89d151..bdd9120bd 100644 --- a/packages/ui/dist/register/chip.js +++ b/packages/ui/dist/register/chip.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Chip } from "../components/chip.js"; -//#region .cache/ui-build/entries/register/chip.js +// .cache/ui-build/entries/register/chip.js var element = registerElement("j3w1-chip", J3w1Chip); -//#endregion export { element }; diff --git a/packages/ui/dist/register/code-editor.js b/packages/ui/dist/register/code-editor.js index 91f3f8d5f..d1025828c 100644 --- a/packages/ui/dist/register/code-editor.js +++ b/packages/ui/dist/register/code-editor.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1CodeEditor } from "../components/code-editor.js"; -//#region .cache/ui-build/entries/register/code-editor.js +// .cache/ui-build/entries/register/code-editor.js var element = registerElement("j3w1-code-editor", J3w1CodeEditor); -//#endregion export { element }; diff --git a/packages/ui/dist/register/combobox.js b/packages/ui/dist/register/combobox.js index 0441f87e8..e914b1233 100644 --- a/packages/ui/dist/register/combobox.js +++ b/packages/ui/dist/register/combobox.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Combobox } from "../components/combobox.js"; -//#region .cache/ui-build/entries/register/combobox.js +// .cache/ui-build/entries/register/combobox.js var element = registerElement("j3w1-combobox", J3w1Combobox); -//#endregion export { element }; diff --git a/packages/ui/dist/register/command-palette.js b/packages/ui/dist/register/command-palette.js index 8c4d129ed..e13961e1c 100644 --- a/packages/ui/dist/register/command-palette.js +++ b/packages/ui/dist/register/command-palette.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1CommandPalette } from "../components/command-palette.js"; -//#region .cache/ui-build/entries/register/command-palette.js +// .cache/ui-build/entries/register/command-palette.js var element = registerElement("j3w1-command-palette", J3w1CommandPalette); -//#endregion export { element }; diff --git a/packages/ui/dist/register/compact-dashboard.js b/packages/ui/dist/register/compact-dashboard.js index 6a2980828..01847187f 100644 --- a/packages/ui/dist/register/compact-dashboard.js +++ b/packages/ui/dist/register/compact-dashboard.js @@ -1,7 +1,6 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import "./chart.js"; import { J3w1CompactDashboard } from "../components/compact-dashboard.js"; -//#region .cache/ui-build/entries/register/compact-dashboard.js +// .cache/ui-build/entries/register/compact-dashboard.js var element = registerElement("j3w1-compact-dashboard", J3w1CompactDashboard); -//#endregion export { element }; diff --git a/packages/ui/dist/register/data-table.js b/packages/ui/dist/register/data-table.js index 4d622c48b..b84bc8231 100644 --- a/packages/ui/dist/register/data-table.js +++ b/packages/ui/dist/register/data-table.js @@ -1,7 +1,6 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import "./menu.js"; import { J3w1DataTable } from "../components/data-table.js"; -//#region .cache/ui-build/entries/register/data-table.js +// .cache/ui-build/entries/register/data-table.js var element = registerElement("j3w1-data-table", J3w1DataTable); -//#endregion export { element }; diff --git a/packages/ui/dist/register/date-picker.js b/packages/ui/dist/register/date-picker.js index 541cd14fa..99d27ba70 100644 --- a/packages/ui/dist/register/date-picker.js +++ b/packages/ui/dist/register/date-picker.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1DatePicker } from "../components/date-picker.js"; -//#region .cache/ui-build/entries/register/date-picker.js +// .cache/ui-build/entries/register/date-picker.js var element = registerElement("j3w1-date-picker", J3w1DatePicker); -//#endregion export { element }; diff --git a/packages/ui/dist/register/description-list.js b/packages/ui/dist/register/description-list.js index 37a62a7a6..b94beeffe 100644 --- a/packages/ui/dist/register/description-list.js +++ b/packages/ui/dist/register/description-list.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1DescriptionList } from "../components/description-list.js"; -//#region .cache/ui-build/entries/register/description-list.js +// .cache/ui-build/entries/register/description-list.js var element = registerElement("j3w1-description-list", J3w1DescriptionList); -//#endregion export { element }; diff --git a/packages/ui/dist/register/diagnostics.js b/packages/ui/dist/register/diagnostics.js index 2d9f84547..46854f8ab 100644 --- a/packages/ui/dist/register/diagnostics.js +++ b/packages/ui/dist/register/diagnostics.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Diagnostics } from "../components/diagnostics.js"; -//#region .cache/ui-build/entries/register/diagnostics.js +// .cache/ui-build/entries/register/diagnostics.js var element = registerElement("j3w1-diagnostics", J3w1Diagnostics); -//#endregion export { element }; diff --git a/packages/ui/dist/register/dialog.js b/packages/ui/dist/register/dialog.js index bded0a66c..5dcb6a328 100644 --- a/packages/ui/dist/register/dialog.js +++ b/packages/ui/dist/register/dialog.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Dialog } from "../components/dialog.js"; -//#region .cache/ui-build/entries/register/dialog.js +// .cache/ui-build/entries/register/dialog.js var element = registerElement("j3w1-dialog", J3w1Dialog); -//#endregion export { element }; diff --git a/packages/ui/dist/register/diff-view.js b/packages/ui/dist/register/diff-view.js index 92fc87c5c..3de702302 100644 --- a/packages/ui/dist/register/diff-view.js +++ b/packages/ui/dist/register/diff-view.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1DiffView } from "../components/diff-view.js"; -//#region .cache/ui-build/entries/register/diff-view.js +// .cache/ui-build/entries/register/diff-view.js var element = registerElement("j3w1-diff-view", J3w1DiffView); -//#endregion export { element }; diff --git a/packages/ui/dist/register/disclosure.js b/packages/ui/dist/register/disclosure.js index 76f4c204b..2734916ec 100644 --- a/packages/ui/dist/register/disclosure.js +++ b/packages/ui/dist/register/disclosure.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Disclosure } from "../components/disclosure.js"; -//#region .cache/ui-build/entries/register/disclosure.js +// .cache/ui-build/entries/register/disclosure.js var element = registerElement("j3w1-disclosure", J3w1Disclosure); -//#endregion export { element }; diff --git a/packages/ui/dist/register/drawer.js b/packages/ui/dist/register/drawer.js index 3ea076673..dcef5181b 100644 --- a/packages/ui/dist/register/drawer.js +++ b/packages/ui/dist/register/drawer.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Drawer } from "../components/drawer.js"; -//#region .cache/ui-build/entries/register/drawer.js +// .cache/ui-build/entries/register/drawer.js var element = registerElement("j3w1-drawer", J3w1Drawer); -//#endregion export { element }; diff --git a/packages/ui/dist/register/editor-search.js b/packages/ui/dist/register/editor-search.js index e0237ca4a..c06a4e9af 100644 --- a/packages/ui/dist/register/editor-search.js +++ b/packages/ui/dist/register/editor-search.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1EditorSearch } from "../components/editor-search.js"; -//#region .cache/ui-build/entries/register/editor-search.js +// .cache/ui-build/entries/register/editor-search.js var element = registerElement("j3w1-editor-search", J3w1EditorSearch); -//#endregion export { element }; diff --git a/packages/ui/dist/register/empty-state.js b/packages/ui/dist/register/empty-state.js index a4b9594da..21cbfbeb4 100644 --- a/packages/ui/dist/register/empty-state.js +++ b/packages/ui/dist/register/empty-state.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1EmptyState } from "../components/empty-state.js"; -//#region .cache/ui-build/entries/register/empty-state.js +// .cache/ui-build/entries/register/empty-state.js var element = registerElement("j3w1-empty-state", J3w1EmptyState); -//#endregion export { element }; diff --git a/packages/ui/dist/register/error-state.js b/packages/ui/dist/register/error-state.js index 5e09ece1b..033288151 100644 --- a/packages/ui/dist/register/error-state.js +++ b/packages/ui/dist/register/error-state.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1ErrorState } from "../components/error-state.js"; -//#region .cache/ui-build/entries/register/error-state.js +// .cache/ui-build/entries/register/error-state.js var element = registerElement("j3w1-error-state", J3w1ErrorState); -//#endregion export { element }; diff --git a/packages/ui/dist/register/field.js b/packages/ui/dist/register/field.js index 875540d71..a70ac0aec 100644 --- a/packages/ui/dist/register/field.js +++ b/packages/ui/dist/register/field.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Field } from "../components/field.js"; -//#region .cache/ui-build/entries/register/field.js +// .cache/ui-build/entries/register/field.js var element = registerElement("j3w1-field", J3w1Field); -//#endregion export { element }; diff --git a/packages/ui/dist/register/fieldset.js b/packages/ui/dist/register/fieldset.js index 4ac632e86..01a3ded77 100644 --- a/packages/ui/dist/register/fieldset.js +++ b/packages/ui/dist/register/fieldset.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Fieldset } from "../components/fieldset.js"; -//#region .cache/ui-build/entries/register/fieldset.js +// .cache/ui-build/entries/register/fieldset.js var element = registerElement("j3w1-fieldset", J3w1Fieldset); -//#endregion export { element }; diff --git a/packages/ui/dist/register/file-browser.js b/packages/ui/dist/register/file-browser.js index 6d8b76ed5..5cb8c5889 100644 --- a/packages/ui/dist/register/file-browser.js +++ b/packages/ui/dist/register/file-browser.js @@ -1,7 +1,6 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import "./tree.js"; import { J3w1FileBrowser } from "../components/file-browser.js"; -//#region .cache/ui-build/entries/register/file-browser.js +// .cache/ui-build/entries/register/file-browser.js var element = registerElement("j3w1-file-browser", J3w1FileBrowser); -//#endregion export { element }; diff --git a/packages/ui/dist/register/file-input.js b/packages/ui/dist/register/file-input.js index 33be9dd6d..789bb5f20 100644 --- a/packages/ui/dist/register/file-input.js +++ b/packages/ui/dist/register/file-input.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1FileInput } from "../components/file-input.js"; -//#region .cache/ui-build/entries/register/file-input.js +// .cache/ui-build/entries/register/file-input.js var element = registerElement("j3w1-file-input", J3w1FileInput); -//#endregion export { element }; diff --git a/packages/ui/dist/register/filterable-table.js b/packages/ui/dist/register/filterable-table.js index 25aeaaee0..4e5aba1ab 100644 --- a/packages/ui/dist/register/filterable-table.js +++ b/packages/ui/dist/register/filterable-table.js @@ -1,7 +1,6 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import "./search-field.js"; import { J3w1FilterableTable } from "../components/filterable-table.js"; -//#region .cache/ui-build/entries/register/filterable-table.js +// .cache/ui-build/entries/register/filterable-table.js var element = registerElement("j3w1-filterable-table", J3w1FilterableTable); -//#endregion export { element }; diff --git a/packages/ui/dist/register/form-builder.js b/packages/ui/dist/register/form-builder.js index c934349f3..2d2e2afb3 100644 --- a/packages/ui/dist/register/form-builder.js +++ b/packages/ui/dist/register/form-builder.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; -import { t as J3w1FormBuilder } from "../chunks/form-builder-BvWZCBPR.js"; -//#region .cache/ui-build/entries/register/form-builder.js +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; +import { t as J3w1FormBuilder } from "../chunks/form-builder-CkeTBQe-.js"; +// .cache/ui-build/entries/register/form-builder.js var element = registerElement("j3w1-form-builder", J3w1FormBuilder); -//#endregion export { element }; diff --git a/packages/ui/dist/register/i3-window-frame.js b/packages/ui/dist/register/i3-window-frame.js index 75e3eb7d6..1de7561c2 100644 --- a/packages/ui/dist/register/i3-window-frame.js +++ b/packages/ui/dist/register/i3-window-frame.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1I3WindowFrame } from "../components/i3-window-frame.js"; -//#region .cache/ui-build/entries/register/i3-window-frame.js +// .cache/ui-build/entries/register/i3-window-frame.js var element = registerElement("j3w1-i3-window-frame", J3w1I3WindowFrame); -//#endregion export { element }; diff --git a/packages/ui/dist/register/icon-button.js b/packages/ui/dist/register/icon-button.js index ffdd0ac88..bc8b0ae7d 100644 --- a/packages/ui/dist/register/icon-button.js +++ b/packages/ui/dist/register/icon-button.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1IconButton } from "../components/icon-button.js"; -//#region .cache/ui-build/entries/register/icon-button.js +// .cache/ui-build/entries/register/icon-button.js var element = registerElement("j3w1-icon-button", J3w1IconButton); -//#endregion export { element }; diff --git a/packages/ui/dist/register/kbd.js b/packages/ui/dist/register/kbd.js index 6ae12a7fc..3b9a265db 100644 --- a/packages/ui/dist/register/kbd.js +++ b/packages/ui/dist/register/kbd.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Kbd } from "../components/kbd.js"; -//#region .cache/ui-build/entries/register/kbd.js +// .cache/ui-build/entries/register/kbd.js var element = registerElement("j3w1-kbd", J3w1Kbd); -//#endregion export { element }; diff --git a/packages/ui/dist/register/link.js b/packages/ui/dist/register/link.js index 669ae18ab..3713e5636 100644 --- a/packages/ui/dist/register/link.js +++ b/packages/ui/dist/register/link.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Link } from "../components/link.js"; -//#region .cache/ui-build/entries/register/link.js +// .cache/ui-build/entries/register/link.js var element = registerElement("j3w1-link", J3w1Link); -//#endregion export { element }; diff --git a/packages/ui/dist/register/list.js b/packages/ui/dist/register/list.js index 2642fae97..abf1291e3 100644 --- a/packages/ui/dist/register/list.js +++ b/packages/ui/dist/register/list.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1List } from "../components/list.js"; -//#region .cache/ui-build/entries/register/list.js +// .cache/ui-build/entries/register/list.js var element = registerElement("j3w1-list", J3w1List); -//#endregion export { element }; diff --git a/packages/ui/dist/register/loading-indicator.js b/packages/ui/dist/register/loading-indicator.js index 5e3a0b442..30ec8f3a6 100644 --- a/packages/ui/dist/register/loading-indicator.js +++ b/packages/ui/dist/register/loading-indicator.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1LoadingIndicator } from "../components/loading-indicator.js"; -//#region .cache/ui-build/entries/register/loading-indicator.js +// .cache/ui-build/entries/register/loading-indicator.js var element = registerElement("j3w1-loading-indicator", J3w1LoadingIndicator); -//#endregion export { element }; diff --git a/packages/ui/dist/register/menu.js b/packages/ui/dist/register/menu.js index 655b77a5a..e99b1d3df 100644 --- a/packages/ui/dist/register/menu.js +++ b/packages/ui/dist/register/menu.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Menu } from "../components/menu.js"; -//#region .cache/ui-build/entries/register/menu.js +// .cache/ui-build/entries/register/menu.js var element = registerElement("j3w1-menu", J3w1Menu); -//#endregion export { element }; diff --git a/packages/ui/dist/register/multiselect.js b/packages/ui/dist/register/multiselect.js index 9183e5e5a..25b412f99 100644 --- a/packages/ui/dist/register/multiselect.js +++ b/packages/ui/dist/register/multiselect.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Multiselect } from "../components/multiselect.js"; -//#region .cache/ui-build/entries/register/multiselect.js +// .cache/ui-build/entries/register/multiselect.js var element = registerElement("j3w1-multiselect", J3w1Multiselect); -//#endregion export { element }; diff --git a/packages/ui/dist/register/number-field.js b/packages/ui/dist/register/number-field.js index 8553c5a33..ed80b7832 100644 --- a/packages/ui/dist/register/number-field.js +++ b/packages/ui/dist/register/number-field.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1NumberField } from "../components/number-field.js"; -//#region .cache/ui-build/entries/register/number-field.js +// .cache/ui-build/entries/register/number-field.js var element = registerElement("j3w1-number-field", J3w1NumberField); -//#endregion export { element }; diff --git a/packages/ui/dist/register/pagination.js b/packages/ui/dist/register/pagination.js index 26680a048..113f449c2 100644 --- a/packages/ui/dist/register/pagination.js +++ b/packages/ui/dist/register/pagination.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Pagination } from "../components/pagination.js"; -//#region .cache/ui-build/entries/register/pagination.js +// .cache/ui-build/entries/register/pagination.js var element = registerElement("j3w1-pagination", J3w1Pagination); -//#endregion export { element }; diff --git a/packages/ui/dist/register/popover.js b/packages/ui/dist/register/popover.js index 5f801317f..48c7a5def 100644 --- a/packages/ui/dist/register/popover.js +++ b/packages/ui/dist/register/popover.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Popover } from "../components/popover.js"; -//#region .cache/ui-build/entries/register/popover.js +// .cache/ui-build/entries/register/popover.js var element = registerElement("j3w1-popover", J3w1Popover); -//#endregion export { element }; diff --git a/packages/ui/dist/register/progress.js b/packages/ui/dist/register/progress.js index 29de54fb7..da67feba7 100644 --- a/packages/ui/dist/register/progress.js +++ b/packages/ui/dist/register/progress.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Progress } from "../components/progress.js"; -//#region .cache/ui-build/entries/register/progress.js +// .cache/ui-build/entries/register/progress.js var element = registerElement("j3w1-progress", J3w1Progress); -//#endregion export { element }; diff --git a/packages/ui/dist/register/radio-group.js b/packages/ui/dist/register/radio-group.js index a41f213ff..e27e5a281 100644 --- a/packages/ui/dist/register/radio-group.js +++ b/packages/ui/dist/register/radio-group.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1RadioGroup } from "../components/radio-group.js"; -//#region .cache/ui-build/entries/register/radio-group.js +// .cache/ui-build/entries/register/radio-group.js var element = registerElement("j3w1-radio-group", J3w1RadioGroup); -//#endregion export { element }; diff --git a/packages/ui/dist/register/range.js b/packages/ui/dist/register/range.js index 63b83eab7..63fda2d7f 100644 --- a/packages/ui/dist/register/range.js +++ b/packages/ui/dist/register/range.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Range } from "../components/range.js"; -//#region .cache/ui-build/entries/register/range.js +// .cache/ui-build/entries/register/range.js var element = registerElement("j3w1-range", J3w1Range); -//#endregion export { element }; diff --git a/packages/ui/dist/register/repeater.js b/packages/ui/dist/register/repeater.js index 6565442ff..eb4811308 100644 --- a/packages/ui/dist/register/repeater.js +++ b/packages/ui/dist/register/repeater.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Repeater } from "../components/repeater.js"; -//#region .cache/ui-build/entries/register/repeater.js +// .cache/ui-build/entries/register/repeater.js var element = registerElement("j3w1-repeater", J3w1Repeater); -//#endregion export { element }; diff --git a/packages/ui/dist/register/search-field.js b/packages/ui/dist/register/search-field.js index 169a29a47..d30d137f6 100644 --- a/packages/ui/dist/register/search-field.js +++ b/packages/ui/dist/register/search-field.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1SearchField } from "../components/search-field.js"; -//#region .cache/ui-build/entries/register/search-field.js +// .cache/ui-build/entries/register/search-field.js var element = registerElement("j3w1-search-field", J3w1SearchField); -//#endregion export { element }; diff --git a/packages/ui/dist/register/segmented-control.js b/packages/ui/dist/register/segmented-control.js index 526fd7f71..5786a67c5 100644 --- a/packages/ui/dist/register/segmented-control.js +++ b/packages/ui/dist/register/segmented-control.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1SegmentedControl } from "../components/segmented-control.js"; -//#region .cache/ui-build/entries/register/segmented-control.js +// .cache/ui-build/entries/register/segmented-control.js var element = registerElement("j3w1-segmented-control", J3w1SegmentedControl); -//#endregion export { element }; diff --git a/packages/ui/dist/register/select.js b/packages/ui/dist/register/select.js index 6fcd3d855..64f3c5936 100644 --- a/packages/ui/dist/register/select.js +++ b/packages/ui/dist/register/select.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Select } from "../components/select.js"; -//#region .cache/ui-build/entries/register/select.js +// .cache/ui-build/entries/register/select.js var element = registerElement("j3w1-select", J3w1Select); -//#endregion export { element }; diff --git a/packages/ui/dist/register/settings-panel.js b/packages/ui/dist/register/settings-panel.js index 0067d590e..ff58d2008 100644 --- a/packages/ui/dist/register/settings-panel.js +++ b/packages/ui/dist/register/settings-panel.js @@ -1,7 +1,6 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import "./switch.js"; import { J3w1SettingsPanel } from "../components/settings-panel.js"; -//#region .cache/ui-build/entries/register/settings-panel.js +// .cache/ui-build/entries/register/settings-panel.js var element = registerElement("j3w1-settings-panel", J3w1SettingsPanel); -//#endregion export { element }; diff --git a/packages/ui/dist/register/sidebar-nav.js b/packages/ui/dist/register/sidebar-nav.js index 59f4cc44a..3c1befc93 100644 --- a/packages/ui/dist/register/sidebar-nav.js +++ b/packages/ui/dist/register/sidebar-nav.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1SidebarNav } from "../components/sidebar-nav.js"; -//#region .cache/ui-build/entries/register/sidebar-nav.js +// .cache/ui-build/entries/register/sidebar-nav.js var element = registerElement("j3w1-sidebar-nav", J3w1SidebarNav); -//#endregion export { element }; diff --git a/packages/ui/dist/register/skeleton.js b/packages/ui/dist/register/skeleton.js index ed0ab489a..e4ef771a6 100644 --- a/packages/ui/dist/register/skeleton.js +++ b/packages/ui/dist/register/skeleton.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Skeleton } from "../components/skeleton.js"; -//#region .cache/ui-build/entries/register/skeleton.js +// .cache/ui-build/entries/register/skeleton.js var element = registerElement("j3w1-skeleton", J3w1Skeleton); -//#endregion export { element }; diff --git a/packages/ui/dist/register/skip-link.js b/packages/ui/dist/register/skip-link.js index 7f93eeef8..e89b5a13a 100644 --- a/packages/ui/dist/register/skip-link.js +++ b/packages/ui/dist/register/skip-link.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1SkipLink } from "../components/skip-link.js"; -//#region .cache/ui-build/entries/register/skip-link.js +// .cache/ui-build/entries/register/skip-link.js var element = registerElement("j3w1-skip-link", J3w1SkipLink); -//#endregion export { element }; diff --git a/packages/ui/dist/register/switch.js b/packages/ui/dist/register/switch.js index 5e227ec0d..c6ab85198 100644 --- a/packages/ui/dist/register/switch.js +++ b/packages/ui/dist/register/switch.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Switch } from "../components/switch.js"; -//#region .cache/ui-build/entries/register/switch.js +// .cache/ui-build/entries/register/switch.js var element = registerElement("j3w1-switch", J3w1Switch); -//#endregion export { element }; diff --git a/packages/ui/dist/register/table.js b/packages/ui/dist/register/table.js index b8eda4f9d..7a9071716 100644 --- a/packages/ui/dist/register/table.js +++ b/packages/ui/dist/register/table.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Table } from "../components/table.js"; -//#region .cache/ui-build/entries/register/table.js +// .cache/ui-build/entries/register/table.js var element = registerElement("j3w1-table", J3w1Table); -//#endregion export { element }; diff --git a/packages/ui/dist/register/tabs.js b/packages/ui/dist/register/tabs.js index 218ebc6da..b11b0c4af 100644 --- a/packages/ui/dist/register/tabs.js +++ b/packages/ui/dist/register/tabs.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Tabs } from "../components/tabs.js"; -//#region .cache/ui-build/entries/register/tabs.js +// .cache/ui-build/entries/register/tabs.js var element = registerElement("j3w1-tabs", J3w1Tabs); -//#endregion export { element }; diff --git a/packages/ui/dist/register/terminal.js b/packages/ui/dist/register/terminal.js index 0f41964d0..622a5164a 100644 --- a/packages/ui/dist/register/terminal.js +++ b/packages/ui/dist/register/terminal.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Terminal } from "../components/terminal.js"; -//#region .cache/ui-build/entries/register/terminal.js +// .cache/ui-build/entries/register/terminal.js var element = registerElement("j3w1-terminal", J3w1Terminal); -//#endregion export { element }; diff --git a/packages/ui/dist/register/text-field.js b/packages/ui/dist/register/text-field.js index 01007e107..53e0c005f 100644 --- a/packages/ui/dist/register/text-field.js +++ b/packages/ui/dist/register/text-field.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1TextField } from "../components/text-field.js"; -//#region .cache/ui-build/entries/register/text-field.js +// .cache/ui-build/entries/register/text-field.js var element = registerElement("j3w1-text-field", J3w1TextField); -//#endregion export { element }; diff --git a/packages/ui/dist/register/textarea.js b/packages/ui/dist/register/textarea.js index 2e9a5db69..36b7b5d3c 100644 --- a/packages/ui/dist/register/textarea.js +++ b/packages/ui/dist/register/textarea.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Textarea } from "../components/textarea.js"; -//#region .cache/ui-build/entries/register/textarea.js +// .cache/ui-build/entries/register/textarea.js var element = registerElement("j3w1-textarea", J3w1Textarea); -//#endregion export { element }; diff --git a/packages/ui/dist/register/time-picker.js b/packages/ui/dist/register/time-picker.js index f69ab0f23..4e31ec582 100644 --- a/packages/ui/dist/register/time-picker.js +++ b/packages/ui/dist/register/time-picker.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1TimePicker } from "../components/time-picker.js"; -//#region .cache/ui-build/entries/register/time-picker.js +// .cache/ui-build/entries/register/time-picker.js var element = registerElement("j3w1-time-picker", J3w1TimePicker); -//#endregion export { element }; diff --git a/packages/ui/dist/register/timeline.js b/packages/ui/dist/register/timeline.js index 6b8f4b354..53dbbcc7b 100644 --- a/packages/ui/dist/register/timeline.js +++ b/packages/ui/dist/register/timeline.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Timeline } from "../components/timeline.js"; -//#region .cache/ui-build/entries/register/timeline.js +// .cache/ui-build/entries/register/timeline.js var element = registerElement("j3w1-timeline", J3w1Timeline); -//#endregion export { element }; diff --git a/packages/ui/dist/register/toast.js b/packages/ui/dist/register/toast.js index 55941b8ec..b0003944d 100644 --- a/packages/ui/dist/register/toast.js +++ b/packages/ui/dist/register/toast.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Toast } from "../components/toast.js"; -//#region .cache/ui-build/entries/register/toast.js +// .cache/ui-build/entries/register/toast.js var element = registerElement("j3w1-toast", J3w1Toast); -//#endregion export { element }; diff --git a/packages/ui/dist/register/toolbar.js b/packages/ui/dist/register/toolbar.js index 0de0d853e..492e4699c 100644 --- a/packages/ui/dist/register/toolbar.js +++ b/packages/ui/dist/register/toolbar.js @@ -1,7 +1,6 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Toolbar } from "../components/toolbar.js"; import "./menu.js"; -//#region .cache/ui-build/entries/register/toolbar.js +// .cache/ui-build/entries/register/toolbar.js var element = registerElement("j3w1-toolbar", J3w1Toolbar); -//#endregion export { element }; diff --git a/packages/ui/dist/register/tooltip.js b/packages/ui/dist/register/tooltip.js index 262fbe4be..2142a8742 100644 --- a/packages/ui/dist/register/tooltip.js +++ b/packages/ui/dist/register/tooltip.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Tooltip } from "../components/tooltip.js"; -//#region .cache/ui-build/entries/register/tooltip.js +// .cache/ui-build/entries/register/tooltip.js var element = registerElement("j3w1-tooltip", J3w1Tooltip); -//#endregion export { element }; diff --git a/packages/ui/dist/register/tree.js b/packages/ui/dist/register/tree.js index 0ecee9bca..eb6e73696 100644 --- a/packages/ui/dist/register/tree.js +++ b/packages/ui/dist/register/tree.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Tree } from "../components/tree.js"; -//#region .cache/ui-build/entries/register/tree.js +// .cache/ui-build/entries/register/tree.js var element = registerElement("j3w1-tree", J3w1Tree); -//#endregion export { element }; diff --git a/packages/ui/dist/register/wizard.js b/packages/ui/dist/register/wizard.js index df8a879a1..075e5d568 100644 --- a/packages/ui/dist/register/wizard.js +++ b/packages/ui/dist/register/wizard.js @@ -1,6 +1,5 @@ -import { n as registerElement } from "../chunks/element-Dovcr9Ky.js"; +import { n as registerElement } from "../chunks/element-DcrNU9Wh.js"; import { J3w1Wizard } from "../components/wizard.js"; -//#region .cache/ui-build/entries/register/wizard.js +// .cache/ui-build/entries/register/wizard.js var element = registerElement("j3w1-wizard", J3w1Wizard); -//#endregion export { element }; diff --git a/site/src/layouts/SiteLayout.astro b/site/src/layouts/SiteLayout.astro index 09a830571..894b3cfcb 100644 --- a/site/src/layouts/SiteLayout.astro +++ b/site/src/layouts/SiteLayout.astro @@ -132,10 +132,10 @@ const canonical = new URL(Astro.url.pathname, Astro.site).href; {theme.version}
-

j3w1 / command

diff --git a/tests/browser/portal.spec.js b/tests/browser/portal.spec.js index 4f759bd40..16de77fbf 100644 --- a/tests/browser/portal.spec.js +++ b/tests/browser/portal.spec.js @@ -38,6 +38,8 @@ test("global command search loads once and finds components, token swatches and await page.goto("./", { waitUntil: "networkidle" }); expect(indexRequests).toBe(0); const opener = page.getByRole("button", { name: "Search the design system", exact: true }); + await expect(opener).toHaveAttribute("aria-keyshortcuts", "Control+k Meta+k"); + if (info.project.name === "desktop") expect((await new AxeBuilder({ page }).include(".site-command [data-open]").analyze()).violations).toEqual([]); await opener.focus(); await page.keyboard.press("Control+k"); const dialog = page.getByRole("dialog");